fix: Rendering not correctly forced when tab changed in certain circumstances (#1817)

- Closes #1811
- Closes #1769
This commit is contained in:
Dermot Duffy
2025-01-09 20:21:26 -08:00
committed by GitHub
parent c3dc4803ad
commit 7657bdf22c
8 changed files with 53 additions and 11 deletions
+1 -1
View File
@@ -157,7 +157,7 @@ export class CameraManager {
return true;
}
public async reset(): Promise<void> {
public async destroy(): Promise<void> {
await this._store.reset();
}
+1 -1
View File
@@ -152,7 +152,7 @@ export class CardElementManager {
// reconnection, to ensure the state subscription/unsubscription works
// correctly for triggers.
this._api.getInitializationManager().uninitialize(InitializationAspect.CAMERAS);
this._api.getCameraManager().reset();
this._api.getCameraManager().destroy();
this._element.removeEventListener(
'mousemove',
@@ -141,6 +141,7 @@ export class ConfigManager {
!isEqual(previousConfig?.cameras_global, this._overriddenConfig?.cameras_global))
) {
this._api.getInitializationManager().uninitialize(InitializationAspect.CAMERAS);
this._api.getCameraManager().destroy();
}
if (
+6
View File
@@ -159,6 +159,9 @@ export class CardController
public getCameraManager(): CameraManager {
return this._cameraManager;
}
public createCameraManager(): void {
this._cameraManager = new CameraManager(this);
}
public getCameraURLManager(): CameraURLManager {
return this._cameraURLManager;
@@ -236,6 +239,9 @@ export class CardController
public getMicrophoneManager(): MicrophoneManager {
return this._microphoneManager;
}
public createMicrophoneManager(): void {
this._microphoneManager = new MicrophoneManager(this);
}
public getQueryStringManager(): QueryStringManager {
return this._queryStringManager;
+15 -6
View File
@@ -92,16 +92,25 @@ export class InitializationManager {
if (
!(await this._initializer.initializeMultipleIfNecessary({
[InitializationAspect.CAMERAS]: async () =>
await this._api.getCameraManager().initializeCamerasFromConfig(),
[InitializationAspect.CAMERAS]: async () => {
// Recreate the camera manager to guarantee an immediate re-render.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1811
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1769
this._api.createCameraManager();
return await this._api.getCameraManager().initializeCamerasFromConfig();
},
// Connecting the microphone (if configured) is considered mandatory to
// avoid issues with some cameras that only allow 2-way audio on the
// first stream initialized. See:
// https://github.com/dermotduffy/frigate-hass-card/issues/1235
// first stream initialized.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1235
...(this._api.getMicrophoneManager().shouldConnectOnInitialization() && {
[InitializationAspect.MICROPHONE_CONNECT]: async () =>
await this._api.getMicrophoneManager().connect(),
[InitializationAspect.MICROPHONE_CONNECT]: async () => {
// Recreate the microphone manager to guarantee an immediate
// re-render.
this._api.createMicrophoneManager();
return await this._api.getMicrophoneManager().connect();
},
}),
}))
) {
+7 -1
View File
@@ -85,6 +85,7 @@ export interface CardConditionAPI {
export interface CardConfigAPI {
getAutomationsManager(): AutomationsManager;
getCameraManager(): CameraManager;
getCardElementManager(): CardElementManager;
getConditionsManager(): ConditionsManager;
getConfigManager(): ConfigManager;
@@ -93,6 +94,7 @@ export interface CardConfigAPI {
getMediaLoadedInfoManager(): MediaLoadedInfoManager;
getMediaPlayerManager(): MediaPlayerManager;
getMessageManager(): MessageManager;
getMicrophoneManager(): MicrophoneManager;
getStatusBarItemManager(): StatusBarItemManager;
getStyleManager(): StyleManager;
getViewManager(): ViewManager;
@@ -165,7 +167,12 @@ export interface CardHASSAPI {
}
export interface CardInitializerAPI {
createCameraManager(): void;
getCameraManager(): CameraManager;
createMicrophoneManager(): void;
getMicrophoneManager(): MicrophoneManager;
getCardElementManager(): CardElementManager;
getConfigManager(): ConfigManager;
getDefaultManager(): DefaultManager;
@@ -173,7 +180,6 @@ export interface CardInitializerAPI {
getHASSManager(): HASSManager;
getMediaPlayerManager(): MediaPlayerManager;
getMessageManager(): MessageManager;
getMicrophoneManager(): MicrophoneManager;
getQueryStringManager(): QueryStringManager;
getResolvedMediaCache(): ResolvedMediaCache;
getViewManager(): ViewManager;
+2 -2
View File
@@ -1290,7 +1290,7 @@ describe('CameraManager', async () => {
});
});
it('should reset', async () => {
it('should destroy', async () => {
const api = createCardAPI();
const engine = mock<CameraManagerEngine>();
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(createHASS());
@@ -1300,7 +1300,7 @@ describe('CameraManager', async () => {
expect(manager.getStore().getCameraCount()).toBe(1);
await manager.reset();
await manager.destroy();
expect(manager.getStore().getCameraCount()).toBe(0);
});
+20
View File
@@ -282,6 +282,26 @@ describe('CardController', () => {
});
});
describe('creaters ', () => {
it('createCameraManager', () => {
const controller = createController();
const original = controller.getCameraManager();
controller.createCameraManager();
expect(controller.getCameraManager()).not.toBe(original);
});
it('createMicrophoneManager', () => {
const controller = createController();
const original = controller.getMicrophoneManager();
controller.createMicrophoneManager();
expect(controller.getMicrophoneManager()).not.toBe(original);
});
});
describe('handlers', () => {
it('hostConnected', () => {
createController().hostConnected();