fix: Improve review media filtering (#2322)

This commit is contained in:
Dermot Duffy
2026-01-24 16:22:12 -08:00
committed by GitHub
parent fc32727860
commit f4e905a7fb
37 changed files with 884 additions and 253 deletions
@@ -1,7 +1,12 @@
import { EffectName, EffectsControllerAPI } from '../../types';
import { Timer } from '../../utils/timer';
import { EffectComponent, EffectModule, EffectOptions } from './types';
const effectRegistry: Record<EffectName, () => Promise<EffectModule>> = {
check: async () => {
const module = await import('../../components/effects/check');
return { default: module.AdvancedCameraCardEffectCheck };
},
fireworks: async () => {
const module = await import('../../components/effects/fireworks');
return { default: module.AdvancedCameraCardEffectFireworks };
@@ -29,6 +34,7 @@ type EffectsContainer = HTMLElement | DocumentFragment;
export class EffectsController implements EffectsControllerAPI {
private _importedModules: Map<EffectName, EffectModule> = new Map();
private _activeInstances: Map<EffectName, EffectComponent | null> = new Map();
private _durationTimers: Map<EffectName, Timer> = new Map();
private _container: EffectsContainer | null = null;
public setContainer(container: EffectsContainer | null): void {
@@ -55,9 +61,28 @@ export class EffectsController implements EffectsControllerAPI {
effectComponent.fadeIn = options?.fadeIn ?? true;
this._container.appendChild(effectComponent);
this._activeInstances.set(name, effectComponent);
const duration = options?.duration;
if (duration !== undefined) {
return new Promise<void>((resolve) => {
const timer = new Timer();
this._durationTimers.set(name, timer);
timer.start(duration, async () => {
this._durationTimers.delete(name);
await this.stopEffect(name);
resolve();
});
});
}
}
public async stopEffect(effect: EffectName): Promise<void> {
const timer = this._durationTimers.get(effect);
if (timer) {
timer.stop();
this._durationTimers.delete(effect);
}
if (!this._activeInstances.has(effect)) {
return;
}
+1
View File
@@ -7,4 +7,5 @@ export type EffectModule = { default: new () => EffectComponent };
export interface EffectOptions {
fadeIn?: boolean;
duration?: number;
}
+13 -4
View File
@@ -22,6 +22,10 @@ export interface OverlayControlsContext {
viewItemManager?: ViewItemManager;
viewManagerEpoch?: ViewManagerEpoch;
capabilities?: ViewItemCapabilities | null;
// Whether to filter reviewed/unreviewed items after changing the reviewed
// state.
filterReviewed?: boolean;
}
export class MediaDetailsController {
@@ -231,7 +235,12 @@ export class MediaDetailsController {
: localize('common.set_reviews.reviewed'),
icon: { icon: isReviewed ? 'mdi:check-circle' : 'mdi:check-circle-outline' },
callback: async () => {
const success = await toggleReviewed(item, context);
const success = await toggleReviewed(
item,
context.viewItemManager,
context.viewManagerEpoch,
context.filterReviewed,
);
return success ? this.getMessage(context) : null;
},
});
@@ -244,7 +253,7 @@ export class MediaDetailsController {
icon: { icon: isFavorite ? 'mdi:star' : 'mdi:star-outline' },
emphasis: isFavorite ? 'medium' : undefined,
callback: async () => {
const success = await toggleFavorite(item, context);
const success = await toggleFavorite(item, context.viewItemManager);
return success ? this.getMessage(context) : null;
},
});
@@ -255,7 +264,7 @@ export class MediaDetailsController {
title: localize('thumbnail.download'),
icon: { icon: 'mdi:download' },
callback: async () => {
await downloadMedia(item, context);
await downloadMedia(item, context.viewItemManager);
// Close overlay message after download.
return null;
@@ -268,7 +277,7 @@ export class MediaDetailsController {
title: localize('thumbnail.timeline'),
icon: { icon: 'mdi:target' },
callback: () => {
navigateToTimeline(item, context);
navigateToTimeline(item, context.viewManagerEpoch);
// Close overlay after timeline navigation
return null;
+4 -1
View File
@@ -432,7 +432,10 @@ export class MenuButtonController {
view?: View | null,
): MenuItem | null {
const selectedItem = view?.queryResults?.getSelectedResult();
if (!ViewItemClassifier.isMedia(selectedItem)) {
if (
!ViewItemClassifier.isMedia(selectedItem) ||
!(view?.isViewerView() || view?.isGalleryView() || view?.is('timeline'))
) {
return null;
}
return {