fix: Panel height should be 100% when casted (#1750)

This commit is contained in:
Dermot Duffy
2024-12-13 08:11:26 -08:00
committed by GitHub
parent e0335c529c
commit ed0bb99a45
7 changed files with 53 additions and 19 deletions
+3 -1
View File
@@ -1,6 +1,7 @@
import { LitElement, ReactiveControllerHost } from 'lit'; import { LitElement, ReactiveControllerHost } from 'lit';
import { ActionEventTarget } from '../action-handler-directive'; import { ActionEventTarget } from '../action-handler-directive';
import { setOrRemoveAttribute } from '../utils/basic'; import { setOrRemoveAttribute } from '../utils/basic';
import { isBeingCasted } from '../utils/casting';
import { isCardInPanel } from '../utils/ha'; import { isCardInPanel } from '../utils/ha';
import { ActionExecutionRequestEventTarget } from './actions/utils/execution-request'; import { ActionExecutionRequestEventTarget } from './actions/utils/execution-request';
import { InitializationAspect } from './initialization-manager'; import { InitializationAspect } from './initialization-manager';
@@ -83,7 +84,7 @@ export class CardElementManager {
// Whether or not the card is in panel mode on the dashboard. // Whether or not the card is in panel mode on the dashboard.
setOrRemoveAttribute(this._element, isCardInPanel(this._element), 'panel'); setOrRemoveAttribute(this._element, isCardInPanel(this._element), 'panel');
setOrRemoveAttribute(this._element, true, 'tabindex', '0'); setOrRemoveAttribute(this._element, isBeingCasted(), 'casted');
this._api.getFullscreenManager().connect(); this._api.getFullscreenManager().connect();
@@ -137,6 +138,7 @@ export class CardElementManager {
public elementDisconnected(): void { public elementDisconnected(): void {
setOrRemoveAttribute(this._element, false, 'panel'); setOrRemoveAttribute(this._element, false, 'panel');
setOrRemoveAttribute(this._element, false, 'tabindex'); setOrRemoveAttribute(this._element, false, 'tabindex');
setOrRemoveAttribute(this._element, false, 'casted');
// When the dashboard 'tab' is changed, the media is effectively unloaded. // When the dashboard 'tab' is changed, the media is effectively unloaded.
this._api.getMediaLoadedInfoManager().clear(); this._api.getMediaLoadedInfoManager().clear();
+5 -16
View File
@@ -15,13 +15,14 @@ import { localize } from '../localize/localize.js';
import { MediaLoadedInfo } from '../types'; import { MediaLoadedInfo } from '../types';
import { import {
createCameraAction, createCameraAction,
createPTZMultiAction,
createDisplayModeAction, createDisplayModeAction,
createGeneralAction,
createMediaPlayerAction, createMediaPlayerAction,
createPTZControlsAction, createPTZControlsAction,
createGeneralAction, createPTZMultiAction,
} from '../utils/action'; } from '../utils/action';
import { isTruthy } from '../utils/basic'; import { isTruthy } from '../utils/basic';
import { isBeingCasted } from '../utils/casting';
import { getEntityIcon, getEntityTitle } from '../utils/ha'; import { getEntityIcon, getEntityTitle } from '../utils/ha';
import { getPTZTarget } from '../utils/ptz'; import { getPTZTarget } from '../utils/ptz';
import { getStreamCameraID, hasSubstream } from '../utils/substream'; import { getStreamCameraID, hasSubstream } from '../utils/substream';
@@ -340,11 +341,7 @@ export class MenuButtonController {
const mediaCapabilities = selectedMedia const mediaCapabilities = selectedMedia
? cameraManager?.getMediaCapabilities(selectedMedia) ? cameraManager?.getMediaCapabilities(selectedMedia)
: null; : null;
if ( if (view?.isViewerView() && mediaCapabilities?.canDownload && !isBeingCasted()) {
view?.isViewerView() &&
mediaCapabilities?.canDownload &&
!this._isBeingCasted()
) {
return { return {
icon: 'mdi:download', icon: 'mdi:download',
...config.menu.buttons.download, ...config.menu.buttons.download,
@@ -429,7 +426,7 @@ export class MenuButtonController {
config: FrigateCardConfig, config: FrigateCardConfig,
inFullscreenMode?: boolean, inFullscreenMode?: boolean,
): MenuItem | null { ): MenuItem | null {
return !this._isBeingCasted() return !isBeingCasted()
? { ? {
icon: inFullscreenMode ? 'mdi:fullscreen-exit' : 'mdi:fullscreen', icon: inFullscreenMode ? 'mdi:fullscreen-exit' : 'mdi:fullscreen',
...config.menu.buttons.fullscreen, ...config.menu.buttons.fullscreen,
@@ -712,12 +709,4 @@ export class MenuButtonController {
} }
return {}; return {};
} }
/**
* Determine if the card is currently being casted.
* @returns
*/
protected _isBeingCasted(): boolean {
return !!navigator.userAgent.match(/CrKey\//);
}
} }
+8 -2
View File
@@ -39,10 +39,16 @@ frigate-card-loading {
:host([dark]) { :host([dark]) {
filter: brightness(75%); filter: brightness(75%);
} }
:host([panel]) { :host([panel]:not([casted])) {
// Card always extends to the full height in panel mode // Card always extends to the full height in panel mode minus the header.
height: calc(100vh - var(--header-height)); height: calc(100vh - var(--header-height));
} }
:host([panel][casted]) {
// Card always extends to the full height in panel mode when casting (there is
// no header).
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1746
height: 100%;
}
div.main { div.main {
position: relative; position: relative;
+7
View File
@@ -0,0 +1,7 @@
/**
* Determine if the card is currently being casted.
* @returns
*/
export const isBeingCasted = (): boolean => {
return !!navigator.userAgent.match(/CrKey\//);
};
@@ -101,6 +101,7 @@ describe('CardElementManager', () => {
manager.elementConnected(); manager.elementConnected();
expect(element.getAttribute('panel')).toBeNull(); expect(element.getAttribute('panel')).toBeNull();
expect(element.getAttribute('casted')).toBeNull();
expect(api.getFullscreenManager().connect).toBeCalled(); expect(api.getFullscreenManager().connect).toBeCalled();
expect(addEventListener).toBeCalledWith( expect(addEventListener).toBeCalledWith(
@@ -134,6 +135,7 @@ describe('CardElementManager', () => {
const element = createLitElement(); const element = createLitElement();
element.setAttribute('panel', ''); element.setAttribute('panel', '');
element.setAttribute('casted', '');
const removeEventListener = vi.fn(); const removeEventListener = vi.fn();
element.removeEventListener = removeEventListener; element.removeEventListener = removeEventListener;
@@ -150,6 +152,7 @@ describe('CardElementManager', () => {
manager.elementDisconnected(); manager.elementDisconnected();
expect(element.getAttribute('panel')).toBeNull(); expect(element.getAttribute('panel')).toBeNull();
expect(element.getAttribute('casted')).toBeNull();
expect(api.getMediaLoadedInfoManager().clear).toBeCalled(); expect(api.getMediaLoadedInfoManager().clear).toBeCalled();
expect(api.getFullscreenManager().disconnect).toBeCalled(); expect(api.getFullscreenManager().disconnect).toBeCalled();
+26
View File
@@ -0,0 +1,26 @@
import { describe, expect, it, vi } from 'vitest';
import { isBeingCasted } from '../../src/utils/casting.js';
describe('isBeingCasted', () => {
it('should confirm being casted', () => {
vi.stubGlobal('navigator', {
userAgent:
'Mozilla/5.0 (Fuchsia) AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/114.0.0.0 Safari/537.36 CrKey/1.56.500000',
});
// Import the function
expect(isBeingCasted()).toBeTruthy();
});
it('should confirm not being casted', () => {
vi.stubGlobal('navigator', {
userAgent:
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/131.0.0.0 Safari/537.36',
});
// Import the function
expect(isBeingCasted()).toBeFalsy();
});
});
+1
View File
@@ -20,6 +20,7 @@ const FULL_COVERAGE_FILES_RELATIVE = [
'utils/audio.ts', 'utils/audio.ts',
'utils/basic.ts', 'utils/basic.ts',
'utils/camera.ts', 'utils/camera.ts',
'utils/casting.ts',
'utils/custom-icons.ts', 'utils/custom-icons.ts',
'utils/debug.ts', 'utils/debug.ts',
'utils/diagnostics.ts', 'utils/diagnostics.ts',