Fix init/select out of sync issues.
This commit is contained in:
@@ -102,9 +102,7 @@ export class FrigateCardCarousel extends LitElement {
|
|||||||
plugins: this.plugins,
|
plugins: this.plugins,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
} else if (changedProps.has('selected')) {
|
||||||
|
|
||||||
if (changedProps.has('selected')) {
|
|
||||||
this._carousel?.selectSlide(this.selected);
|
this._carousel?.selectSlide(this.selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -434,7 +434,9 @@ export class FrigateCardLiveCarousel extends LitElement {
|
|||||||
|
|
||||||
protected _getSelectedCameraIndex(): number {
|
protected _getSelectedCameraIndex(): number {
|
||||||
const cameraIDs = this.cameraManager?.getStore().getVisibleCameraIDs();
|
const cameraIDs = this.cameraManager?.getStore().getVisibleCameraIDs();
|
||||||
if (!cameraIDs || !this.view) {
|
if (!cameraIDs || !this.view || this.viewFilterCameraID) {
|
||||||
|
// If the carousel is limited to a single cameraID, the first (only)
|
||||||
|
// element is always the selected one.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return Math.max(0, Array.from(cameraIDs).indexOf(this.view.camera));
|
return Math.max(0, Array.from(cameraIDs).indexOf(this.view.camera));
|
||||||
|
|||||||
+18
-13
@@ -6,7 +6,7 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
unsafeCSS,
|
unsafeCSS,
|
||||||
} from 'lit';
|
} from 'lit';
|
||||||
import { customElement, property } from 'lit/decorators.js';
|
import { customElement, property, state } from 'lit/decorators.js';
|
||||||
import { guard } from 'lit/directives/guard.js';
|
import { guard } from 'lit/directives/guard.js';
|
||||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||||
@@ -223,8 +223,8 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public cameraManager?: CameraManager;
|
public cameraManager?: CameraManager;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@state()
|
||||||
public selected = 0;
|
protected _selected = 0;
|
||||||
|
|
||||||
protected _media: ViewMedia[] | null = null;
|
protected _media: ViewMedia[] | null = null;
|
||||||
protected _titleTimer = new Timer();
|
protected _titleTimer = new Timer();
|
||||||
@@ -298,12 +298,12 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
*/
|
*/
|
||||||
protected _getMediaNeighbors(): MediaNeighbors | null {
|
protected _getMediaNeighbors(): MediaNeighbors | null {
|
||||||
const mediaCount = this._media?.length ?? 0;
|
const mediaCount = this._media?.length ?? 0;
|
||||||
if (!this._media || this.selected === null) {
|
if (!this._media) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevIndex = this.selected > 0 ? this.selected - 1 : null;
|
const prevIndex = this._selected > 0 ? this._selected - 1 : null;
|
||||||
const nextIndex = this.selected + 1 < mediaCount ? this.selected + 1 : null;
|
const nextIndex = this._selected + 1 < mediaCount ? this._selected + 1 : null;
|
||||||
return {
|
return {
|
||||||
...(prevIndex !== null && {
|
...(prevIndex !== null && {
|
||||||
previous: {
|
previous: {
|
||||||
@@ -325,7 +325,7 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selected === null || this.selected === index) {
|
if (this._selected === index) {
|
||||||
// The slide may already be selected on load, so don't dispatch a new view
|
// The slide may already be selected on load, so don't dispatch a new view
|
||||||
// unless necessary (i.e. the new index is different from the current
|
// unless necessary (i.e. the new index is different from the current
|
||||||
// index).
|
// index).
|
||||||
@@ -408,10 +408,10 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
this.view?.queryResults?.getSelectedIndex(this.viewFilterCameraID) ?? 0;
|
this.view?.queryResults?.getSelectedIndex(this.viewFilterCameraID) ?? 0;
|
||||||
const newSeek = this.view?.context?.mediaViewer?.seek;
|
const newSeek = this.view?.context?.mediaViewer?.seek;
|
||||||
|
|
||||||
if (newMedia !== this._media || newSelected !== this.selected || !newSeek) {
|
if (newMedia !== this._media || newSelected !== this._selected || !newSeek) {
|
||||||
setOrRemoveAttribute(this, false, 'unseekable');
|
setOrRemoveAttribute(this, false, 'unseekable');
|
||||||
this._media = newMedia;
|
this._media = newMedia;
|
||||||
this.selected = newSelected;
|
this._selected = newSelected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,7 +427,7 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
// If there's no selected media, just choose the last (most recent one) to
|
// If there's no selected media, just choose the last (most recent one) to
|
||||||
// avoid rendering a blank. This situation should not occur in practice, as
|
// avoid rendering a blank. This situation should not occur in practice, as
|
||||||
// this view should not be called without a selected media.
|
// this view should not be called without a selected media.
|
||||||
const selectedMedia = this._media[this.selected] ?? this._media[mediaCount - 1];
|
const selectedMedia = this._media[this._selected] ?? this._media[mediaCount - 1];
|
||||||
|
|
||||||
if (!this.hass || !this.cameraManager || !selectedMedia) {
|
if (!this.hass || !this.cameraManager || !selectedMedia) {
|
||||||
return;
|
return;
|
||||||
@@ -460,7 +460,7 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
<frigate-card-carousel
|
<frigate-card-carousel
|
||||||
.dragEnabled=${this.viewerConfig?.draggable ?? true}
|
.dragEnabled=${this.viewerConfig?.draggable ?? true}
|
||||||
.plugins=${guard([this.viewerConfig, this._media], this._getPlugins.bind(this))}
|
.plugins=${guard([this.viewerConfig, this._media], this._getPlugins.bind(this))}
|
||||||
.selected=${this.selected ?? 0}
|
.selected=${this._selected}
|
||||||
transitionEffect=${this._getTransitionEffect()}
|
transitionEffect=${this._getTransitionEffect()}
|
||||||
@frigate-card:carousel:select=${(ev: CustomEvent<CarouselSelected>) => {
|
@frigate-card:carousel:select=${(ev: CustomEvent<CarouselSelected>) => {
|
||||||
this._setViewSelectedIndex(ev.detail.index);
|
this._setViewSelectedIndex(ev.detail.index);
|
||||||
@@ -526,10 +526,15 @@ export class FrigateCardViewerCarousel extends LitElement {
|
|||||||
*/
|
*/
|
||||||
protected async _seekHandler(): Promise<void> {
|
protected async _seekHandler(): Promise<void> {
|
||||||
const seek = this.view?.context?.mediaViewer?.seek;
|
const seek = this.view?.context?.mediaViewer?.seek;
|
||||||
if (!this.hass || !seek || !this._media || this.selected === null || !this._player) {
|
if (
|
||||||
|
!this.hass ||
|
||||||
|
!seek ||
|
||||||
|
!this._media ||
|
||||||
|
!this._player
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const selectedMedia = this._media[this.selected];
|
const selectedMedia = this._media[this._selected];
|
||||||
if (!selectedMedia) {
|
if (!selectedMedia) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,10 +137,11 @@ export class CarouselController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const getCarouselSelectedObject = (): CarouselSelected | null => {
|
const getCarouselSelectedObject = (): CarouselSelected | null => {
|
||||||
const selectedIndex = this.getSelectedIndex();
|
// Caution: Must use methods/accessors of the new carousel, not the public
|
||||||
const slide = this.getSlide(selectedIndex);
|
// API of this controller which may use a different carousel.
|
||||||
|
const selectedIndex = carousel.selectedScrollSnap();
|
||||||
if (selectedIndex !== null && slide) {
|
const slide = carousel.slideNodes()[selectedIndex] ?? null;
|
||||||
|
if (slide) {
|
||||||
return {
|
return {
|
||||||
index: selectedIndex,
|
index: selectedIndex,
|
||||||
element: slide,
|
element: slide,
|
||||||
@@ -160,7 +161,6 @@ export class CarouselController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
carousel.on('init', () => selectSlide());
|
|
||||||
carousel.on('select', () => selectSlide());
|
carousel.on('select', () => selectSlide());
|
||||||
carousel.on('settle', () => {
|
carousel.on('settle', () => {
|
||||||
const carouselSelected = getCarouselSelectedObject();
|
const carouselSelected = getCarouselSelectedObject();
|
||||||
|
|||||||
Reference in New Issue
Block a user