Initial attempt add hiding elements during loading.
This commit is contained in:
+49
-34
@@ -99,6 +99,7 @@ import { supportsFeature } from './utils/ha/update.js';
|
|||||||
import { isValidMediaShowInfo } from './utils/media-info.js';
|
import { isValidMediaShowInfo } from './utils/media-info.js';
|
||||||
import { View } from './view.js';
|
import { View } from './view.js';
|
||||||
import pkg from '../package.json';
|
import pkg from '../package.json';
|
||||||
|
import { ViewContext } from 'view';
|
||||||
|
|
||||||
/** A note on media callbacks:
|
/** A note on media callbacks:
|
||||||
*
|
*
|
||||||
@@ -184,8 +185,9 @@ export class FrigateCard extends LitElement {
|
|||||||
// Automated refreshes of the default view.
|
// Automated refreshes of the default view.
|
||||||
protected _updateTimerID: number | null = null;
|
protected _updateTimerID: number | null = null;
|
||||||
|
|
||||||
// Information about the most recently loaded media item.
|
// Information about loaded media items.
|
||||||
protected _mediaShowInfo: MediaShowInfo | null = null;
|
protected _currentMediaShowInfo: MediaShowInfo | null = null;
|
||||||
|
protected _lastValidMediaShowInfo: MediaShowInfo | null = null;
|
||||||
|
|
||||||
// Array of dynamic menu buttons to be added to menu.
|
// Array of dynamic menu buttons to be added to menu.
|
||||||
protected _dynamicMenuButtons: MenuButton[] = [];
|
protected _dynamicMenuButtons: MenuButton[] = [];
|
||||||
@@ -331,7 +333,11 @@ export class FrigateCard extends LitElement {
|
|||||||
for (const action of actions) {
|
for (const action of actions) {
|
||||||
// All frigate card actions will have action of 'fire-dom-event' and
|
// All frigate card actions will have action of 'fire-dom-event' and
|
||||||
// styling only applies to those.
|
// styling only applies to those.
|
||||||
if (!action || action.action !== 'fire-dom-event' || !('frigate_card_action' in action)) {
|
if (
|
||||||
|
!action ||
|
||||||
|
action.action !== 'fire-dom-event' ||
|
||||||
|
!('frigate_card_action' in action)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const frigateCardAction = action as FrigateCardCustomAction;
|
const frigateCardAction = action as FrigateCardCustomAction;
|
||||||
@@ -925,6 +931,15 @@ export class FrigateCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected _changeView(args?: { view?: View; resetMessage?: boolean }): void {
|
protected _changeView(args?: { view?: View; resetMessage?: boolean }): void {
|
||||||
|
const changeView = (view: View): void => {
|
||||||
|
if (View.isMediaChange(this._view, view)) {
|
||||||
|
this._currentMediaShowInfo = null;
|
||||||
|
}
|
||||||
|
this._view = view;
|
||||||
|
this._generateConditionState();
|
||||||
|
this._resetMainScroll();
|
||||||
|
};
|
||||||
|
|
||||||
if (args?.resetMessage ?? true) {
|
if (args?.resetMessage ?? true) {
|
||||||
this._message = null;
|
this._message = null;
|
||||||
}
|
}
|
||||||
@@ -945,21 +960,19 @@ export class FrigateCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (camera) {
|
if (camera) {
|
||||||
this._view = new View({
|
changeView(
|
||||||
|
new View({
|
||||||
view: this._getConfig().view.default,
|
view: this._getConfig().view.default,
|
||||||
camera: camera,
|
camera: camera,
|
||||||
});
|
}),
|
||||||
this._generateConditionState();
|
);
|
||||||
this._resetMainScroll();
|
|
||||||
|
|
||||||
// Restart the update timer, so the default view is refreshed at a fixed
|
// Restart the update timer, so the default view is refreshed at a fixed
|
||||||
// interval from now (if so configured).
|
// interval from now (if so configured).
|
||||||
this._startUpdateTimer();
|
this._startUpdateTimer();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._view = args.view;
|
changeView(args.view);
|
||||||
this._generateConditionState();
|
|
||||||
this._resetMainScroll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -987,6 +1000,15 @@ export class FrigateCard extends LitElement {
|
|||||||
this._changeView({ view: e.detail });
|
this._changeView({ view: e.detail });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add view context to the current view.
|
||||||
|
* @param ev A ViewContext event.
|
||||||
|
*/
|
||||||
|
protected _addViewContextHandler(ev: CustomEvent<ViewContext>): void {
|
||||||
|
this._changeView({
|
||||||
|
view: this._view?.clone().mergeInContext(ev.detail),
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Called before each update.
|
* Called before each update.
|
||||||
*/
|
*/
|
||||||
@@ -1592,7 +1614,7 @@ export class FrigateCard extends LitElement {
|
|||||||
*/
|
*/
|
||||||
protected _resetMainScroll(): void {
|
protected _resetMainScroll(): void {
|
||||||
// Reset the scroll on the main div to the top.
|
// Reset the scroll on the main div to the top.
|
||||||
this._refMain.value?.scroll({top: 0});
|
this._refMain.value?.scroll({ top: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1614,20 +1636,12 @@ export class FrigateCard extends LitElement {
|
|||||||
if (!isValidMediaShowInfo(mediaShowInfo)) {
|
if (!isValidMediaShowInfo(mediaShowInfo)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let requestRefresh = false;
|
|
||||||
if (
|
|
||||||
this._view?.isGalleryView() &&
|
|
||||||
(mediaShowInfo.width != this._mediaShowInfo?.width ||
|
|
||||||
mediaShowInfo.height != this._mediaShowInfo?.height)
|
|
||||||
) {
|
|
||||||
requestRefresh = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._mediaShowInfo = mediaShowInfo;
|
this._lastValidMediaShowInfo = this._currentMediaShowInfo = mediaShowInfo;
|
||||||
if (requestRefresh) {
|
|
||||||
|
// An update may be required to draw elements.
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler called when fullscreen is toggled.
|
* Handler called when fullscreen is toggled.
|
||||||
@@ -1702,8 +1716,8 @@ export class FrigateCard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const aspectRatioMode = this._getConfig().dimensions.aspect_ratio_mode;
|
const aspectRatioMode = this._getConfig().dimensions.aspect_ratio_mode;
|
||||||
if (aspectRatioMode == 'dynamic' && this._mediaShowInfo) {
|
if (aspectRatioMode == 'dynamic' && this._lastValidMediaShowInfo) {
|
||||||
return `${this._mediaShowInfo.width} / ${this._mediaShowInfo.height}`;
|
return `${this._lastValidMediaShowInfo.width} / ${this._lastValidMediaShowInfo.height}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultAspectRatio = this._getConfig().dimensions.aspect_ratio;
|
const defaultAspectRatio = this._getConfig().dimensions.aspect_ratio;
|
||||||
@@ -1776,16 +1790,14 @@ export class FrigateCard extends LitElement {
|
|||||||
style="${styleMap(cardStyle)}"
|
style="${styleMap(cardStyle)}"
|
||||||
@action=${(ev: CustomEvent) => this._actionHandler(ev, actions)}
|
@action=${(ev: CustomEvent) => this._actionHandler(ev, actions)}
|
||||||
@ll-custom=${this._cardActionHandler.bind(this)}
|
@ll-custom=${this._cardActionHandler.bind(this)}
|
||||||
@frigate-card:message=${this._messageHandler}
|
@frigate-card:message=${this._messageHandler.bind(this)}
|
||||||
@frigate-card:change-view=${this._changeViewHandler}
|
@frigate-card:view:change=${this._changeViewHandler.bind(this)}
|
||||||
|
@frigate-card:view:change-context=${this._addViewContextHandler.bind(this)}
|
||||||
@frigate-card:media-show=${this._mediaShowHandler}
|
@frigate-card:media-show=${this._mediaShowHandler}
|
||||||
@frigate-card:render=${() => this.requestUpdate()}
|
@frigate-card:render=${() => this.requestUpdate()}
|
||||||
>
|
>
|
||||||
${renderMenuAbove ? this._renderMenu() : ''}
|
${renderMenuAbove ? this._renderMenu() : ''}
|
||||||
<div
|
<div ${ref(this._refMain)} class="main">
|
||||||
${ref(this._refMain)}
|
|
||||||
class="main"
|
|
||||||
>
|
|
||||||
${this._cameras === undefined && !this._message
|
${this._cameras === undefined && !this._message
|
||||||
? until(
|
? until(
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -1807,9 +1819,12 @@ export class FrigateCard extends LitElement {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
${!renderMenuAbove ? this._renderMenu() : ''}
|
${!renderMenuAbove ? this._renderMenu() : ''}
|
||||||
${!this._message && this._getConfig().elements
|
${!this._message &&
|
||||||
|
(!this._view?.isAnyMediaView() || this._currentMediaShowInfo) &&
|
||||||
|
this._getConfig().elements
|
||||||
? // Elements need to render after the main views so it can render 'on
|
? // Elements need to render after the main views so it can render 'on
|
||||||
// top'.
|
// top', but only if the view is a non-media view or the media is
|
||||||
|
// already loaded.
|
||||||
html` <frigate-card-elements
|
html` <frigate-card-elements
|
||||||
${ref(this._refElements)}
|
${ref(this._refElements)}
|
||||||
.hass=${this._hass}
|
.hass=${this._hass}
|
||||||
@@ -1925,8 +1940,8 @@ export class FrigateCard extends LitElement {
|
|||||||
* @returns The Lovelace card size in units of 50px.
|
* @returns The Lovelace card size in units of 50px.
|
||||||
*/
|
*/
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
if (this._mediaShowInfo) {
|
if (this._lastValidMediaShowInfo) {
|
||||||
return this._mediaShowInfo.height / 50;
|
return this._lastValidMediaShowInfo.height / 50;
|
||||||
}
|
}
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-5
@@ -44,7 +44,10 @@ import {
|
|||||||
WebRTCCardConfig,
|
WebRTCCardConfig,
|
||||||
} from '../types.js';
|
} from '../types.js';
|
||||||
import { stopEventFromActivatingCardWideActions } from '../utils/action.js';
|
import { stopEventFromActivatingCardWideActions } from '../utils/action.js';
|
||||||
import { contentsChanged, errorToConsole } from '../utils/basic.js';
|
import {
|
||||||
|
contentsChanged,
|
||||||
|
errorToConsole,
|
||||||
|
} from '../utils/basic.js';
|
||||||
import { getCameraIcon, getCameraTitle } from '../utils/camera.js';
|
import { getCameraIcon, getCameraTitle } from '../utils/camera.js';
|
||||||
import { homeAssistantSignPath } from '../utils/ha';
|
import { homeAssistantSignPath } from '../utils/ha';
|
||||||
import { getFullDependentBrowseMediaQueryParameters } from '../utils/ha/browse-media.js';
|
import { getFullDependentBrowseMediaQueryParameters } from '../utils/ha/browse-media.js';
|
||||||
@@ -52,7 +55,7 @@ import {
|
|||||||
dispatchExistingMediaShowInfoAsEvent,
|
dispatchExistingMediaShowInfoAsEvent,
|
||||||
dispatchMediaShowEvent,
|
dispatchMediaShowEvent,
|
||||||
} from '../utils/media-info.js';
|
} from '../utils/media-info.js';
|
||||||
import { View } from '../view.js';
|
import { dispatchViewContextChangeEvent, View } from '../view.js';
|
||||||
import { AutoMediaPlugin } from './embla-plugins/automedia.js';
|
import { AutoMediaPlugin } from './embla-plugins/automedia.js';
|
||||||
import { Lazyload } from './embla-plugins/lazyload.js';
|
import { Lazyload } from './embla-plugins/lazyload.js';
|
||||||
import {
|
import {
|
||||||
@@ -226,7 +229,7 @@ export class FrigateCardLive extends LitElement {
|
|||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@frigate-card:change-view=${(ev: CustomEvent<View>) => {
|
@frigate-card:view:change=${(ev: CustomEvent<View>) => {
|
||||||
if (this._inBackground) {
|
if (this._inBackground) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
}
|
}
|
||||||
@@ -448,10 +451,13 @@ export class FrigateCardLiveCarousel extends LitElement {
|
|||||||
.evolve({
|
.evolve({
|
||||||
camera: Array.from(this.cameras.keys())[selectedCameraIndex],
|
camera: Array.from(this.cameras.keys())[selectedCameraIndex],
|
||||||
|
|
||||||
// Reset the target so thumbnails will be re-fetched.
|
// Reset the target.
|
||||||
target: null,
|
target: null,
|
||||||
childIndex: null,
|
childIndex: null,
|
||||||
})
|
})
|
||||||
|
// Don't yet fetch thumbnails (they will be fetched when the carousel
|
||||||
|
// settles).
|
||||||
|
.mergeInContext({ thumbnails: { fetch: false } })
|
||||||
.dispatchChangeEvent(this);
|
.dispatchChangeEvent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +588,11 @@ export class FrigateCardLiveCarousel extends LitElement {
|
|||||||
.label="${title ? `${localize('common.live')}: ${title}` : ''}"
|
.label="${title ? `${localize('common.live')}: ${title}` : ''}"
|
||||||
.titlePopupConfig=${config.controls.title}
|
.titlePopupConfig=${config.controls.title}
|
||||||
transitionEffect=${this._getTransitionEffect()}
|
transitionEffect=${this._getTransitionEffect()}
|
||||||
@frigate-card:carousel:settle=${this._setViewHandler.bind(this)}
|
@frigate-card:media-carousel:select=${this._setViewHandler.bind(this)}
|
||||||
|
@frigate-card:carousel:settle=${() => {
|
||||||
|
// Fetch the thumbnails after the carousel has settled.
|
||||||
|
dispatchViewContextChangeEvent(this, { thumbnails: { fetch: true }});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<frigate-card-next-previous-control
|
<frigate-card-next-previous-control
|
||||||
slot="previous"
|
slot="previous"
|
||||||
|
|||||||
@@ -363,6 +363,16 @@ export class FrigateCardMediaCarousel extends LitElement {
|
|||||||
@frigate-card:carousel:select=${(ev: CustomEvent<CarouselSelect>) => {
|
@frigate-card:carousel:select=${(ev: CustomEvent<CarouselSelect>) => {
|
||||||
this._slideResizeObserver.disconnect();
|
this._slideResizeObserver.disconnect();
|
||||||
this._slideResizeObserver.observe(ev.detail.element);
|
this._slideResizeObserver.observe(ev.detail.element);
|
||||||
|
|
||||||
|
// Pass up the media-carousel select event first to allow parents to
|
||||||
|
// initialize/reset before the media info is dispatched.
|
||||||
|
dispatchFrigateCardEvent<CarouselSelect>(
|
||||||
|
this,
|
||||||
|
'media-carousel:select',
|
||||||
|
ev.detail,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dispatch media info.
|
||||||
this._dispatchMediaShowInfo();
|
this._dispatchMediaShowInfo();
|
||||||
}}
|
}}
|
||||||
@frigate-card:carousel:media-show=${this._storeMediaShowInfo.bind(this)}
|
@frigate-card:carousel:media-show=${this._storeMediaShowInfo.bind(this)}
|
||||||
|
|||||||
@@ -27,6 +27,17 @@ import { dispatchFrigateCardErrorEvent } from './message.js';
|
|||||||
import './surround.js';
|
import './surround.js';
|
||||||
import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
|
import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
|
||||||
|
|
||||||
|
interface ThumbnailViewContext {
|
||||||
|
// Whetherr or not to fetch thumbnails.
|
||||||
|
fetch?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'view' {
|
||||||
|
interface ViewContext {
|
||||||
|
thumbnails?: ThumbnailViewContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@customElement('frigate-card-surround-thumbnails')
|
@customElement('frigate-card-surround-thumbnails')
|
||||||
export class FrigateCardSurround extends LitElement {
|
export class FrigateCardSurround extends LitElement {
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
@@ -64,7 +75,8 @@ export class FrigateCardSurround extends LitElement {
|
|||||||
!this.config ||
|
!this.config ||
|
||||||
this.config.mode === 'none' ||
|
this.config.mode === 'none' ||
|
||||||
this.view.target ||
|
this.view.target ||
|
||||||
!this.browseMediaParams
|
!this.browseMediaParams ||
|
||||||
|
!(this.view.context?.thumbnails?.fetch ?? true)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -147,7 +159,7 @@ export class FrigateCardSurround extends LitElement {
|
|||||||
.target=${this.view.target}
|
.target=${this.view.target}
|
||||||
.selected=${this.view.childIndex}
|
.selected=${this.view.childIndex}
|
||||||
.cameras=${this.cameras}
|
.cameras=${this.cameras}
|
||||||
@frigate-card:change-view=${(ev: CustomEvent) => changeDrawer(ev, 'close')}
|
@frigate-card:view:change=${(ev: CustomEvent) => changeDrawer(ev, 'close')}
|
||||||
@frigate-card:thumbnail-carousel:tap=${(ev: CustomEvent<ThumbnailCarouselTap>) => {
|
@frigate-card:thumbnail-carousel:tap=${(ev: CustomEvent<ThumbnailCarouselTap>) => {
|
||||||
// Send the view change from the source of the tap event, so the
|
// Send the view change from the source of the tap event, so the
|
||||||
// view change will be caught by the handler above (to close the drawer).
|
// view change will be caught by the handler above (to close the drawer).
|
||||||
|
|||||||
@@ -282,8 +282,8 @@ export class FrigateCardThumbnail extends LitElement {
|
|||||||
view: 'timeline',
|
view: 'timeline',
|
||||||
target: this.target,
|
target: this.target,
|
||||||
childIndex: this.childIndex ?? null,
|
childIndex: this.childIndex ?? null,
|
||||||
context: {},
|
|
||||||
})
|
})
|
||||||
|
.removeContext('timeline')
|
||||||
.dispatchChangeEvent(this);
|
.dispatchChangeEvent(this);
|
||||||
} else if (recording) {
|
} else if (recording) {
|
||||||
this.view
|
this.view
|
||||||
@@ -291,7 +291,9 @@ export class FrigateCardThumbnail extends LitElement {
|
|||||||
view: 'timeline',
|
view: 'timeline',
|
||||||
target: null,
|
target: null,
|
||||||
childIndex: null,
|
childIndex: null,
|
||||||
context: {
|
})
|
||||||
|
.mergeInContext({
|
||||||
|
timeline: {
|
||||||
window: {
|
window: {
|
||||||
start: fromUnixTime(recording.start_time),
|
start: fromUnixTime(recording.start_time),
|
||||||
end: fromUnixTime(recording.end_time),
|
end: fromUnixTime(recording.end_time),
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { customElement, property } from 'lit/decorators.js';
|
|||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
|
import { ViewContext } from 'view';
|
||||||
import { DataSet } from 'vis-data/esnext';
|
import { DataSet } from 'vis-data/esnext';
|
||||||
import {
|
import {
|
||||||
DataGroupCollectionType,
|
DataGroupCollectionType,
|
||||||
@@ -64,7 +65,7 @@ import {
|
|||||||
isTrueMedia,
|
isTrueMedia,
|
||||||
multipleBrowseMediaQuery,
|
multipleBrowseMediaQuery,
|
||||||
} from '../utils/ha/browse-media';
|
} from '../utils/ha/browse-media';
|
||||||
import { View, ViewContext } from '../view';
|
import { View } from '../view';
|
||||||
import { dispatchFrigateCardErrorEvent, dispatchMessageEvent } from './message.js';
|
import { dispatchFrigateCardErrorEvent, dispatchMessageEvent } from './message.js';
|
||||||
import './surround-thumbnails.js';
|
import './surround-thumbnails.js';
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ interface FrigateCardTimelineItem extends TimelineItem {
|
|||||||
source?: FrigateBrowseMediaSource;
|
source?: FrigateBrowseMediaSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TimelineViewContext extends ViewContext {
|
interface TimelineViewContext {
|
||||||
// The selected timeline window.
|
// The selected timeline window.
|
||||||
window?: TimelineWindow;
|
window?: TimelineWindow;
|
||||||
|
|
||||||
@@ -89,6 +90,12 @@ interface TimelineViewContext extends ViewContext {
|
|||||||
dateFetch?: Date;
|
dateFetch?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'view' {
|
||||||
|
interface ViewContext {
|
||||||
|
timeline?: TimelineViewContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type TimelineMediaType = 'all' | 'clips' | 'snapshots';
|
type TimelineMediaType = 'all' | 'clips' | 'snapshots';
|
||||||
|
|
||||||
interface CameraRecordings {
|
interface CameraRecordings {
|
||||||
@@ -867,8 +874,8 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
?.evolve({
|
?.evolve({
|
||||||
target: thumbnails?.target ?? null,
|
target: thumbnails?.target ?? null,
|
||||||
childIndex: thumbnails?.childIndex ?? null,
|
childIndex: thumbnails?.childIndex ?? null,
|
||||||
context: this._generateViewContext(true),
|
|
||||||
})
|
})
|
||||||
|
.mergeInContext(this._generateTimelineContext(true))
|
||||||
.dispatchChangeEvent(this);
|
.dispatchChangeEvent(this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1174,7 +1181,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
|
|
||||||
// Regenerate the thumbnails after the selection, to allow the new selection
|
// Regenerate the thumbnails after the selection, to allow the new selection
|
||||||
// to be in the generated view.
|
// to be in the generated view.
|
||||||
const context = this.view.context as TimelineViewContext | null;
|
const context = this.view.context?.timeline;
|
||||||
const timelineWindow = this._timeline.getWindow();
|
const timelineWindow = this._timeline.getWindow();
|
||||||
|
|
||||||
if (context?.window) {
|
if (context?.window) {
|
||||||
@@ -1222,8 +1229,8 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
?.evolve({
|
?.evolve({
|
||||||
target: thumbnails?.target ?? null,
|
target: thumbnails?.target ?? null,
|
||||||
childIndex: thumbnails?.childIndex ?? null,
|
childIndex: thumbnails?.childIndex ?? null,
|
||||||
context: this._generateViewContext(false),
|
|
||||||
})
|
})
|
||||||
|
.mergeInContext(this._generateTimelineContext(false))
|
||||||
.dispatchChangeEvent(this);
|
.dispatchChangeEvent(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1234,9 +1241,10 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
* the window is preserved if it is already in the context.
|
* the window is preserved if it is already in the context.
|
||||||
* @returns The TimelineViewContext object.
|
* @returns The TimelineViewContext object.
|
||||||
*/
|
*/
|
||||||
protected _generateViewContext(addWindow: boolean): TimelineViewContext {
|
protected _generateTimelineContext(addWindow: boolean): ViewContext {
|
||||||
const currentContext = this.view?.context as TimelineViewContext | undefined;
|
const currentContext = this.view?.context?.timeline;
|
||||||
const newContext: TimelineViewContext = {};
|
const newContext: TimelineViewContext = {}
|
||||||
|
|
||||||
if (addWindow && this._timeline) {
|
if (addWindow && this._timeline) {
|
||||||
newContext.window = this._timeline.getWindow();
|
newContext.window = this._timeline.getWindow();
|
||||||
} else if (currentContext?.window) {
|
} else if (currentContext?.window) {
|
||||||
@@ -1245,7 +1253,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
if (this._data.lastFetchDate) {
|
if (this._data.lastFetchDate) {
|
||||||
newContext.dateFetch = this._data.lastFetchDate;
|
newContext.dateFetch = this._data.lastFetchDate;
|
||||||
}
|
}
|
||||||
return newContext || null;
|
return Object.keys(newContext) ? {timeline: newContext} : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
.label="${this.view.media.title}"
|
.label="${this.view.media.title}"
|
||||||
.titlePopupConfig=${this.viewerConfig?.controls.title}
|
.titlePopupConfig=${this.viewerConfig?.controls.title}
|
||||||
transitionEffect=${this._getTransitionEffect()}
|
transitionEffect=${this._getTransitionEffect()}
|
||||||
@frigate-card:carousel:select=${this._setViewHandler.bind(this)}
|
@frigate-card:media-carousel:select=${this._setViewHandler.bind(this)}
|
||||||
@frigate-card:media-show=${this._recordingSeekHandler.bind(this)}
|
@frigate-card:media-show=${this._recordingSeekHandler.bind(this)}
|
||||||
>
|
>
|
||||||
<frigate-card-next-previous-control
|
<frigate-card-next-previous-control
|
||||||
|
|||||||
Vendored
+5
@@ -1,2 +1,7 @@
|
|||||||
declare module '*.scss';
|
declare module '*.scss';
|
||||||
declare module '*.jpg';
|
declare module '*.jpg';
|
||||||
|
declare module "view" {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
interface ViewContext {
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
-5
@@ -1,15 +1,13 @@
|
|||||||
|
import { ViewContext } from 'view';
|
||||||
import {
|
import {
|
||||||
FrigateBrowseMediaSource,
|
FrigateBrowseMediaSource,
|
||||||
FrigateCardUserSpecifiedView,
|
FrigateCardUserSpecifiedView,
|
||||||
FrigateCardView,
|
FrigateCardView,
|
||||||
FRIGATE_CARD_VIEWS_USER_SPECIFIED,
|
FRIGATE_CARD_VIEWS_USER_SPECIFIED,
|
||||||
FRIGATE_CARD_VIEW_DEFAULT
|
FRIGATE_CARD_VIEW_DEFAULT,
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
import { dispatchFrigateCardEvent } from './utils/basic.js';
|
import { dispatchFrigateCardEvent } from './utils/basic.js';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface ViewContext {}
|
|
||||||
|
|
||||||
export interface ViewEvolveParameters {
|
export interface ViewEvolveParameters {
|
||||||
view?: FrigateCardView;
|
view?: FrigateCardView;
|
||||||
camera?: string;
|
camera?: string;
|
||||||
@@ -63,6 +61,26 @@ export class View {
|
|||||||
: FRIGATE_CARD_VIEW_DEFAULT;
|
: FRIGATE_CARD_VIEW_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if a view change represents a major "media change" for the given
|
||||||
|
* view.
|
||||||
|
* @param prev The previous view.
|
||||||
|
* @param curr The current view.
|
||||||
|
* @returns True if the view change is a real media change.
|
||||||
|
*/
|
||||||
|
public static isMediaChange(prev?: View, curr?: View): boolean {
|
||||||
|
return (
|
||||||
|
!prev ||
|
||||||
|
!curr ||
|
||||||
|
prev.view !== curr.view ||
|
||||||
|
prev.camera !== curr.camera ||
|
||||||
|
// When in the live view, the target/childIndex are the events that
|
||||||
|
// happened in the past -- not reflective of the actual live media viewer.
|
||||||
|
(curr.view !== 'live' &&
|
||||||
|
(prev.target !== curr.target || prev.childIndex !== curr.childIndex))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a view.
|
* Clone a view.
|
||||||
*/
|
*/
|
||||||
@@ -96,6 +114,28 @@ export class View {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge view contexts.
|
||||||
|
* @param context The context to merge in.
|
||||||
|
* @returns This view.
|
||||||
|
*/
|
||||||
|
public mergeInContext(context: ViewContext): View {
|
||||||
|
this.context = { ...this.context, ...context };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a context key.
|
||||||
|
* @param key The key to remove.
|
||||||
|
* @returns This view.
|
||||||
|
*/
|
||||||
|
public removeContext(key: keyof ViewContext): View {
|
||||||
|
if (this.context) {
|
||||||
|
delete(this.context[key]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if current view matches a named view.
|
* Determine if current view matches a named view.
|
||||||
*/
|
*/
|
||||||
@@ -168,6 +208,18 @@ export class View {
|
|||||||
* @param target The target dispatching the event.
|
* @param target The target dispatching the event.
|
||||||
*/
|
*/
|
||||||
public dispatchChangeEvent(target: EventTarget): void {
|
public dispatchChangeEvent(target: EventTarget): void {
|
||||||
dispatchFrigateCardEvent(target, 'change-view', this);
|
dispatchFrigateCardEvent(target, 'view:change', this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch an event to change the view context.
|
||||||
|
* @param target The EventTarget to send the event from.
|
||||||
|
* @param context The context to change.
|
||||||
|
*/
|
||||||
|
export const dispatchViewContextChangeEvent = (
|
||||||
|
target: EventTarget,
|
||||||
|
context: ViewContext,
|
||||||
|
): void => {
|
||||||
|
dispatchFrigateCardEvent(target, 'view:change-context', context);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user