fix: Fix issues with lazy loading and overridden configuration (#2012)
- Closes #2011
This commit is contained in:
@@ -7,22 +7,25 @@ export class LazyLoadController implements ReactiveController {
|
|||||||
private _host: ReactiveControllerHost & HTMLElement;
|
private _host: ReactiveControllerHost & HTMLElement;
|
||||||
private _documentVisible = true;
|
private _documentVisible = true;
|
||||||
private _intersects = false;
|
private _intersects = false;
|
||||||
private _loaded: boolean;
|
private _loaded = false;
|
||||||
private _unloadConditions: LazyUnloadCondition[] | null = null;
|
private _unloadConditions: LazyUnloadCondition[] | null = null;
|
||||||
private _intersectionObserver = new IntersectionObserver(
|
private _intersectionObserver = new IntersectionObserver(
|
||||||
this._intersectionHandler.bind(this),
|
this._intersectionHandler.bind(this),
|
||||||
);
|
);
|
||||||
private _listeners: LazyLoadListener[] = [];
|
private _listeners: LazyLoadListener[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(host: ReactiveControllerHost & HTMLElement) {
|
||||||
host: ReactiveControllerHost & HTMLElement,
|
this._host = host;
|
||||||
|
this._host.addController(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setConfiguration(
|
||||||
lazyLoad?: boolean,
|
lazyLoad?: boolean,
|
||||||
lazyUnloadConditions?: LazyUnloadCondition[],
|
lazyUnloadConditions?: LazyUnloadCondition[],
|
||||||
) {
|
) {
|
||||||
this._host = host;
|
if (!lazyLoad && !this._loaded) {
|
||||||
this._host.addController(this);
|
this._setLoaded(true);
|
||||||
|
}
|
||||||
this._loaded = !lazyLoad;
|
|
||||||
this._unloadConditions = lazyUnloadConditions ?? null;
|
this._unloadConditions = lazyUnloadConditions ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
|||||||
protected _showStreamTroubleshooting = false;
|
protected _showStreamTroubleshooting = false;
|
||||||
|
|
||||||
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
||||||
protected _lazyLoadController: LazyLoadController | null = null;
|
protected _lazyLoadController: LazyLoadController = new LazyLoadController(this);
|
||||||
|
|
||||||
// A note on dynamic imports:
|
// A note on dynamic imports:
|
||||||
//
|
//
|
||||||
@@ -83,6 +83,16 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
|||||||
// background. These calls fail without waiting for loading here.
|
// background. These calls fail without waiting for loading here.
|
||||||
protected _importPromises: Promise<unknown>[] = [];
|
protected _importPromises: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._lazyLoadController.addListener((loaded: boolean) => {
|
||||||
|
if (!loaded) {
|
||||||
|
this._isVideoMediaLoaded = false;
|
||||||
|
dispatchMediaUnloadedEvent(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
|
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
return (await this._refProvider.value?.getMediaPlayerController()) ?? null;
|
return (await this._refProvider.value?.getMediaPlayerController()) ?? null;
|
||||||
@@ -145,19 +155,10 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
|||||||
changedProps.has('liveConfig') ||
|
changedProps.has('liveConfig') ||
|
||||||
(!this._lazyLoadController && this.liveConfig)
|
(!this._lazyLoadController && this.liveConfig)
|
||||||
) {
|
) {
|
||||||
this._lazyLoadController?.destroy();
|
this._lazyLoadController.setConfiguration(
|
||||||
this._lazyLoadController?.removeController();
|
|
||||||
this._lazyLoadController = new LazyLoadController(
|
|
||||||
this,
|
|
||||||
this.liveConfig?.lazy_load,
|
this.liveConfig?.lazy_load,
|
||||||
this.liveConfig?.lazy_unload,
|
this.liveConfig?.lazy_unload,
|
||||||
);
|
);
|
||||||
this._lazyLoadController.addListener((loaded: boolean) => {
|
|
||||||
if (!loaded) {
|
|
||||||
this._isVideoMediaLoaded = false;
|
|
||||||
dispatchMediaUnloadedEvent(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProps.has('liveConfig')) {
|
if (changedProps.has('liveConfig')) {
|
||||||
|
|||||||
@@ -69,11 +69,16 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
|||||||
public cardWideConfig?: CardWideConfig;
|
public cardWideConfig?: CardWideConfig;
|
||||||
|
|
||||||
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
||||||
protected _lazyLoadController: LazyLoadController | null = null;
|
protected _lazyLoadController: LazyLoadController = new LazyLoadController(this);
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
protected _url: string | null = null;
|
protected _url: string | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._lazyLoadController.addListener((loaded) => loaded && this._setURL());
|
||||||
|
}
|
||||||
|
|
||||||
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
|
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
return (await this._refProvider.value?.getMediaPlayerController()) ?? null;
|
return (await this._refProvider.value?.getMediaPlayerController()) ?? null;
|
||||||
@@ -184,13 +189,7 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
|||||||
changedProps.has('viewerConfig') ||
|
changedProps.has('viewerConfig') ||
|
||||||
(!this._lazyLoadController && this.viewerConfig)
|
(!this._lazyLoadController && this.viewerConfig)
|
||||||
) {
|
) {
|
||||||
this._lazyLoadController?.destroy();
|
this._lazyLoadController.setConfiguration(this.viewerConfig?.lazy_load);
|
||||||
this._lazyLoadController?.removeController();
|
|
||||||
this._lazyLoadController = new LazyLoadController(
|
|
||||||
this,
|
|
||||||
this.viewerConfig?.lazy_load,
|
|
||||||
);
|
|
||||||
this._lazyLoadController.addListener((loaded) => loaded && this._setURL());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -37,13 +37,14 @@ describe('LazyLoadController', () => {
|
|||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be loaded by default', () => {
|
it('should be unloaded by default', () => {
|
||||||
const controller = new LazyLoadController(createLitElement());
|
const controller = new LazyLoadController(createLitElement());
|
||||||
expect(controller.isLoaded()).toBe(true);
|
expect(controller.isLoaded()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be loaded by default when lazy load is set to true', () => {
|
it('should not be loaded by default when lazy load is set to true', () => {
|
||||||
const controller = new LazyLoadController(createLitElement(), true);
|
const controller = new LazyLoadController(createLitElement());
|
||||||
|
controller.setConfiguration(true);
|
||||||
expect(controller.isLoaded()).toBe(false);
|
expect(controller.isLoaded()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -61,10 +62,8 @@ describe('LazyLoadController', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should remove handlers and listeners on destroy', () => {
|
it('should remove handlers and listeners on destroy', () => {
|
||||||
const controller = new LazyLoadController(createLitElement(), true, [
|
const controller = new LazyLoadController(createLitElement());
|
||||||
'unselected',
|
controller.setConfiguration(true, ['unselected', 'hidden']);
|
||||||
'hidden',
|
|
||||||
]);
|
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
|
|
||||||
const listener = vi.fn();
|
const listener = vi.fn();
|
||||||
@@ -84,9 +83,26 @@ describe('LazyLoadController', () => {
|
|||||||
expect(listener).not.toBeCalled();
|
expect(listener).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('should set configuration', () => {
|
||||||
|
it('should set loaded if lazy loading set to false', () => {
|
||||||
|
const listener = vi.fn();
|
||||||
|
const controller = new LazyLoadController(createLitElement());
|
||||||
|
controller.addListener(listener);
|
||||||
|
|
||||||
|
expect(controller.isLoaded()).toBe(false);
|
||||||
|
expect(listener).not.toBeCalled();
|
||||||
|
|
||||||
|
controller.setConfiguration(false);
|
||||||
|
|
||||||
|
expect(controller.isLoaded()).toBe(true);
|
||||||
|
expect(listener).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('should lazy load', () => {
|
describe('should lazy load', () => {
|
||||||
it('should load when both visible and intersecting', () => {
|
it('should load when both visible and intersecting', () => {
|
||||||
const controller = new LazyLoadController(createLitElement(), true);
|
const controller = new LazyLoadController(createLitElement());
|
||||||
|
controller.setConfiguration(true);
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
|
|
||||||
expect(controller.isLoaded()).toBe(false);
|
expect(controller.isLoaded()).toBe(false);
|
||||||
@@ -102,6 +118,9 @@ describe('LazyLoadController', () => {
|
|||||||
describe('should lazy unload', () => {
|
describe('should lazy unload', () => {
|
||||||
it('should unload on DOM disconnection', () => {
|
it('should unload on DOM disconnection', () => {
|
||||||
const controller = new LazyLoadController(createLitElement());
|
const controller = new LazyLoadController(createLitElement());
|
||||||
|
|
||||||
|
// No lazy loading.
|
||||||
|
controller.setConfiguration(false);
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
|
|
||||||
expect(controller.isLoaded()).toBe(true);
|
expect(controller.isLoaded()).toBe(true);
|
||||||
@@ -127,11 +146,8 @@ describe('LazyLoadController', () => {
|
|||||||
])(
|
])(
|
||||||
'when unload conditions are: %s',
|
'when unload conditions are: %s',
|
||||||
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
||||||
const controller = new LazyLoadController(
|
const controller = new LazyLoadController(createLitElement());
|
||||||
createLitElement(),
|
controller.setConfiguration(true, unloadConditions);
|
||||||
true,
|
|
||||||
unloadConditions,
|
|
||||||
);
|
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
|
|
||||||
callIntersectionHandler(true);
|
callIntersectionHandler(true);
|
||||||
@@ -153,11 +169,8 @@ describe('LazyLoadController', () => {
|
|||||||
])(
|
])(
|
||||||
'when unload conditions are: %s',
|
'when unload conditions are: %s',
|
||||||
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
(unloadConditions: LazyUnloadCondition[], shouldBeLoaded: boolean) => {
|
||||||
const controller = new LazyLoadController(
|
const controller = new LazyLoadController(createLitElement());
|
||||||
createLitElement(),
|
controller.setConfiguration(true, unloadConditions);
|
||||||
true,
|
|
||||||
unloadConditions,
|
|
||||||
);
|
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
|
|
||||||
callIntersectionHandler(true);
|
callIntersectionHandler(true);
|
||||||
@@ -173,10 +186,8 @@ describe('LazyLoadController', () => {
|
|||||||
|
|
||||||
it('should call listeners', () => {
|
it('should call listeners', () => {
|
||||||
const listener = vi.fn();
|
const listener = vi.fn();
|
||||||
const controller = new LazyLoadController(createLitElement(), true, [
|
const controller = new LazyLoadController(createLitElement());
|
||||||
'unselected',
|
controller.setConfiguration(true, ['unselected', 'hidden']);
|
||||||
'hidden',
|
|
||||||
]);
|
|
||||||
controller.hostConnected();
|
controller.hostConnected();
|
||||||
controller.addListener(listener);
|
controller.addListener(listener);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user