diff --git a/src/components/thumbnail/feature/feature.ts b/src/components/thumbnail/feature/feature.ts index f7014eff..e73d90a4 100644 --- a/src/components/thumbnail/feature/feature.ts +++ b/src/components/thumbnail/feature/feature.ts @@ -167,13 +167,16 @@ export class AdvancedCameraCardThumbnailFeature extends LitElement { }} @click=${async (ev: Event) => { stopEventFromActivatingCardWideActions(ev); - if (this.item) { - await toggleReviewed( + if ( + this.item && + (await toggleReviewed( this.item, this.viewItemManager, this.viewManagerEpoch, this.filterReviewed, - ); + )) + ) { + this.requestUpdate(); } }} >` diff --git a/src/view/unified-query-builder.ts b/src/view/unified-query-builder.ts index fc87764c..152f0ece 100644 --- a/src/view/unified-query-builder.ts +++ b/src/view/unified-query-builder.ts @@ -355,9 +355,11 @@ export class UnifiedQueryBuilder { return null; } - return this._buildQueryNodesCapabilityUnchecked(spec, cameraID, { - limit: options?.limit, - }); + return this._buildQueryNodesCapabilityUnchecked( + spec, + cameraID, + this._resolveReviewedFilter(spec, cameraID, options), + ); } // ========================================================================= @@ -399,21 +401,13 @@ export class UnifiedQueryBuilder { continue; } - // For reviews, resolve the reviewed filter from camera config if not provided - const resolvedOptions = - cameraSpec.mediaType === 'reviews' && options?.reviewed === undefined - ? { - ...options, - reviewed: getReviewedQueryFilterFromConfig( - this._cameraManager.getStore().getCameraConfig(cameraID)?.media - ?.reviewed, - ), - } - : options; - this._addNode( query, - this._buildQueryNodesCapabilityUnchecked(cameraSpec, cameraID, resolvedOptions), + this._buildQueryNodesCapabilityUnchecked( + cameraSpec, + cameraID, + this._resolveReviewedFilter(cameraSpec, cameraID, options), + ), ); } return query.hasNodes() ? query : null; @@ -530,6 +524,22 @@ export class UnifiedQueryBuilder { }; } + private _resolveReviewedFilter( + spec: MediaTypeSpec, + cameraID: string, + options?: QueryFiltersOptions, + ): QueryFiltersOptions | undefined { + if (spec.mediaType !== 'reviews' || options?.reviewed !== undefined) { + return options; + } + return { + ...options, + reviewed: getReviewedQueryFilterFromConfig( + this._cameraManager.getStore().getCameraConfig(cameraID)?.media?.reviewed, + ), + }; + } + private _extractFilterOptions(options?: QueryFilters): QueryFilters { return { ...(options?.favorite !== undefined && { favorite: options.favorite }), diff --git a/tests/view/unified-query-builder.test.ts b/tests/view/unified-query-builder.test.ts index ca36bd14..2fb56a4f 100644 --- a/tests/view/unified-query-builder.test.ts +++ b/tests/view/unified-query-builder.test.ts @@ -652,6 +652,91 @@ describe('UnifiedQueryBuilder', () => { assert(isReviewQuery(query.getNodes()[0])); }); + it('should apply reviewed filter from config for reviews query', () => { + const { cameraManager, foldersManager, store } = createMocks(); + store.getCameraIDs.mockReturnValue(new Set(['camera.office'])); + store.getCameraConfig.mockReturnValue( + createCameraConfig({ media: { type: 'auto', reviewed: 'unreviewed' } }), + ); + + cameraManager.getCameraCapabilities.mockReturnValue( + createCapabilities({ reviews: true }), + ); + + const builder = new UnifiedQueryBuilder(cameraManager, foldersManager); + const query = builder.buildDefaultCameraQuery(); + + assert(query); + expect(query.getNodes()[0]).toMatchObject({ + type: QueryType.Review, + reviewed: false, + }); + }); + + it('should apply reviewed=true filter from config', () => { + const { cameraManager, foldersManager, store } = createMocks(); + store.getCameraIDs.mockReturnValue(new Set(['camera.office'])); + store.getCameraConfig.mockReturnValue( + createCameraConfig({ media: { type: 'auto', reviewed: 'reviewed' } }), + ); + + cameraManager.getCameraCapabilities.mockReturnValue( + createCapabilities({ reviews: true }), + ); + + const builder = new UnifiedQueryBuilder(cameraManager, foldersManager); + const query = builder.buildDefaultCameraQuery(); + + assert(query); + expect(query.getNodes()[0]).toMatchObject({ + type: QueryType.Review, + reviewed: true, + }); + }); + + it('should not apply reviewed filter when config is all', () => { + const { cameraManager, foldersManager, store } = createMocks(); + store.getCameraIDs.mockReturnValue(new Set(['camera.office'])); + store.getCameraConfig.mockReturnValue( + createCameraConfig({ media: { type: 'auto', reviewed: 'all' } }), + ); + + cameraManager.getCameraCapabilities.mockReturnValue( + createCapabilities({ reviews: true }), + ); + + const builder = new UnifiedQueryBuilder(cameraManager, foldersManager); + const query = builder.buildDefaultCameraQuery(); + + assert(query); + assert(isReviewQuery(query.getNodes()[0])); + expect(query.getNodes()[0]).not.toHaveProperty('reviewed'); + }); + + it('should not apply reviewed filter to non-review queries', () => { + const { cameraManager, foldersManager, store } = createMocks(); + store.getCameraIDs.mockReturnValue(new Set(['camera.office'])); + store.getCameraConfig.mockReturnValue( + createCameraConfig({ + media: { type: 'auto', reviewed: 'unreviewed' }, + }), + ); + + cameraManager.getCameraCapabilities.mockReturnValue( + createCapabilities({ clips: true }), + ); + + const builder = new UnifiedQueryBuilder(cameraManager, foldersManager); + const query = builder.buildDefaultCameraQuery(); + + assert(query); + expect(query.getNodes()[0]).toMatchObject({ + type: QueryType.Event, + hasClip: true, + }); + expect(query.getNodes()[0]).not.toHaveProperty('reviewed'); + }); + it('should build clips query for camera with clips capability', () => { const { cameraManager, foldersManager, store } = createMocks(); store.getCameraIDs.mockReturnValue(new Set(['camera.office']));