Fixes for Firefox.
This commit is contained in:
@@ -32,6 +32,7 @@ export class CachedValueController<T> implements ReactiveController {
|
||||
*/
|
||||
public updateValue(): void {
|
||||
this._value = this._callback();
|
||||
this._startTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,12 +40,13 @@ export class CachedValueController<T> implements ReactiveController {
|
||||
*/
|
||||
public clearValue(): void {
|
||||
this._value = undefined;
|
||||
this._stopTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the timer.
|
||||
*/
|
||||
public stopTimer(): void {
|
||||
protected _stopTimer(): void {
|
||||
clearInterval(this._timerID);
|
||||
this._timerID = undefined;
|
||||
}
|
||||
@@ -52,8 +54,8 @@ export class CachedValueController<T> implements ReactiveController {
|
||||
/**
|
||||
* Enable the timer. Repeated calls will have no effect.
|
||||
*/
|
||||
public startTimer(): void {
|
||||
this.stopTimer();
|
||||
protected _startTimer(): void {
|
||||
this._stopTimer();
|
||||
if (this._timerSeconds > 0) {
|
||||
this._timerID = window.setInterval(() => {
|
||||
this.updateValue();
|
||||
@@ -67,7 +69,6 @@ export class CachedValueController<T> implements ReactiveController {
|
||||
*/
|
||||
hostConnected(): void {
|
||||
this.updateValue();
|
||||
this.startTimer();
|
||||
this._host.requestUpdate();
|
||||
}
|
||||
|
||||
@@ -75,6 +76,6 @@ export class CachedValueController<T> implements ReactiveController {
|
||||
* Host has disconnected from the cache.
|
||||
*/
|
||||
hostDisconnected(): void {
|
||||
this.stopTimer();
|
||||
this.clearValue();
|
||||
}
|
||||
}
|
||||
|
||||
+61
-7
@@ -38,7 +38,7 @@ export class FrigateCardImage extends LitElement {
|
||||
protected _image?: HTMLImageElement;
|
||||
|
||||
protected _cachedValueController?: CachedValueController<string>;
|
||||
|
||||
protected _boundVisibilityHandler = this._visibilityHandler.bind(this);
|
||||
/**
|
||||
* Set the image configuration.
|
||||
*/
|
||||
@@ -52,7 +52,6 @@ export class FrigateCardImage extends LitElement {
|
||||
this._imageConfig.refresh_seconds,
|
||||
this._getImageSource.bind(this),
|
||||
);
|
||||
this._cachedValueController.startTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +68,7 @@ export class FrigateCardImage extends LitElement {
|
||||
* @returns `true` if the element should be updated.
|
||||
*/
|
||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||
if (!this.hass) {
|
||||
if (!this.hass || document.visibilityState !== 'visible') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -95,10 +94,10 @@ export class FrigateCardImage extends LitElement {
|
||||
this._imageConfig?.mode === 'camera' &&
|
||||
cameraEntity) {
|
||||
if (shouldUpdateBasedOnHass(this.hass, changedProps.get('hass'), [cameraEntity])) {
|
||||
// Image needs to update if the image view is in camera mode and the camera
|
||||
// entity changes, as this could be a security token change.
|
||||
this._cachedValueController?.updateValue();
|
||||
this._cachedValueController?.startTimer();
|
||||
// If the state of the camera entity has changed, remove the cached
|
||||
// value (will be re-calculated in willUpdate). This is important to
|
||||
// ensure a changed access token is immediately used.
|
||||
this._cachedValueController?.clearValue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -106,6 +105,61 @@ export class FrigateCardImage extends LitElement {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ensure there is a cached value before an update.
|
||||
* @param _changedProps The changed properties
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected willUpdate(_changedProps: PropertyValues): void {
|
||||
if (!this._cachedValueController?.value) {
|
||||
this._cachedValueController?.updateValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component connected callback.
|
||||
*/
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
document.addEventListener('visibilitychange', this._boundVisibilityHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component disconnected callback.
|
||||
*/
|
||||
disconnectedCallback(): void {
|
||||
document.removeEventListener('visibilitychange', this._boundVisibilityHandler);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle document visibility changes.
|
||||
*/
|
||||
protected _visibilityHandler(): void {
|
||||
if (!this._image) {
|
||||
return;
|
||||
}
|
||||
if (document.visibilityState === 'hidden') {
|
||||
// Set the image to default when the document is hidden. This is to avoid
|
||||
// some browsers (e.g. Firefox) eagerly re-loading the old image when the
|
||||
// document regains visibility -- for some images (e.g. camera mode) the
|
||||
// image may be using an old-expired token and re-use prior to
|
||||
// re-generation of a new URL would generate an unauthorized request
|
||||
// (401), see:
|
||||
// https://github.com/dermotduffy/frigate-hass-card/issues/398
|
||||
this._cachedValueController?.clearValue();
|
||||
this._image.src = defaultImage;
|
||||
} else {
|
||||
// If the document is freshly re-visible, immediately re-render it to
|
||||
// restore the image src. If the HASS object is old (i.e. browser tab was
|
||||
// inactive for some time) this update request may be (correctly)
|
||||
// rejected.
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a working absolute image URL that the browser will not cache.
|
||||
* @param url An input URL (may be relative to document origin)
|
||||
|
||||
Reference in New Issue
Block a user