From 14dad831ee577b078c86855927d4e282aedf712a Mon Sep 17 00:00:00 2001 From: midzelis Date: Wed, 8 Oct 2025 17:01:31 +0000 Subject: [PATCH] Review comments, minus renames --- .../lib/components/timeline/Timeline.svelte | 20 ++--- .../PhotostreamManager.svelte.ts | 81 ++++++------------- .../PhotostreamSegment.svelte.ts | 51 +++++------- .../internal/layout-support.svelte.ts | 2 +- .../timeline-manager/month-group.svelte.ts | 24 +++--- .../timeline-manager.svelte.spec.ts | 47 +++++++---- .../timeline-manager.svelte.ts | 18 +++-- web/src/lib/utils/asset-utils.ts | 2 +- web/src/lib/utils/cancellable-task.ts | 23 ++++-- web/src/lib/utils/timeline-util.ts | 9 --- 10 files changed, 121 insertions(+), 156 deletions(-) diff --git a/web/src/lib/components/timeline/Timeline.svelte b/web/src/lib/components/timeline/Timeline.svelte index b883b5c489..c04fad1896 100644 --- a/web/src/lib/components/timeline/Timeline.svelte +++ b/web/src/lib/components/timeline/Timeline.svelte @@ -11,7 +11,7 @@ import Skeleton from '$lib/elements/Skeleton.svelte'; import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte'; import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte'; - import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; + import { getSegmentIdentifier, TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; import { assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte'; import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; @@ -19,12 +19,7 @@ import { isSelectingAllAssets } from '$lib/stores/assets-store.svelte'; import { mobileDevice } from '$lib/stores/mobile-device.svelte'; import { navigate } from '$lib/utils/navigation'; - import { - getSegmentIdentifier, - getTimes, - type ScrubberListener, - type TimelineYearMonth, - } from '$lib/utils/timeline-util'; + import { getTimes, type ScrubberListener, type TimelineYearMonth } from '$lib/utils/timeline-util'; import { type AlbumResponseDto, type PersonResponseDto } from '@immich/sdk'; import { DateTime } from 'luxon'; import { onMount, type Snippet } from 'svelte'; @@ -272,11 +267,6 @@ } }); - const getMaxScrollPercent = () => { - const totalHeight = timelineManager.timelineHeight + bottomSectionHeight + timelineManager.topSectionHeight; - return (totalHeight - timelineManager.viewportHeight) / totalHeight; - }; - const getMaxScroll = () => { if (!element || !timelineElement) { return 0; @@ -288,7 +278,7 @@ const scrollToMonthGroupAndOffset = (monthGroup: MonthGroup, monthGroupScrollPercent: number) => { const topOffset = monthGroup.top; - const maxScrollPercent = getMaxScrollPercent(); + const maxScrollPercent = timelineManager.maxScrollPercent; const delta = monthGroup.height * monthGroupScrollPercent; const scrollToTop = (topOffset + delta) * maxScrollPercent; @@ -343,7 +333,7 @@ return; } - let maxScrollPercent = getMaxScrollPercent(); + let maxScrollPercent = timelineManager.maxScrollPercent; let found = false; const monthsLength = timelineManager.months.length; @@ -640,7 +630,7 @@ {@const display = monthGroup.intersecting} {@const absoluteHeight = monthGroup.top} - {#if !monthGroup.isLoaded} + {#if !monthGroup.loaded}
this.months.reduce((accumulator, b) => accumulator + b.height, 0) + this.topSectionHeight, ); @@ -71,6 +69,17 @@ export abstract class PhotostreamManager { } } + abstract get months(): PhotostreamSegment[]; + + get maxScrollPercent() { + const totalHeight = this.timelineHeight + this.bottomSectionHeight + this.topSectionHeight; + return (totalHeight - this.viewportHeight) / totalHeight; + } + + get maxScroll() { + return this.topSectionHeight + this.bottomSectionHeight + (this.timelineHeight - this.viewportHeight); + } + #setHeaderHeight(value: number) { if (this.#headerHeight == value) { return false; @@ -151,6 +160,10 @@ export abstract class PhotostreamManager { return this.#viewportHeight; } + get hasEmptyViewport() { + return this.viewportWidth === 0 || this.viewportHeight === 0; + } + updateSlidingWindow(scrollTop: number) { if (this.#scrollTop !== scrollTop) { this.#scrollTop = scrollTop; @@ -198,34 +211,12 @@ export abstract class PhotostreamManager { await this.initTask.execute(() => Promise.resolve(undefined), true); } - public destroy() { + destroy() { this.isInitialized = false; } - async updateViewport(viewport: Viewport) { - if (viewport.height === 0 && viewport.width === 0) { - return; - } - - if (this.viewportHeight === viewport.height && this.viewportWidth === viewport.width) { - return; - } - - if (!this.initTask.executed) { - await (this.initTask.loading ? this.initTask.waitUntilCompletion() : this.init()); - } - - const changedWidth = viewport.width !== this.viewportWidth; - this.viewportHeight = viewport.height; - this.viewportWidth = viewport.width; - this.updateViewportGeometry(changedWidth); - } - protected updateViewportGeometry(changedWidth: boolean) { - if (!this.isInitialized) { - return; - } - if (this.viewportWidth === 0 || this.viewportHeight === 0) { + if (!this.isInitialized || this.hasEmptyViewport) { return; } for (const month of this.months) { @@ -246,29 +237,18 @@ export abstract class PhotostreamManager { } async loadSegment(identifier: SegmentIdentifier, options?: { cancelable: boolean }): Promise { - let cancelable = true; - if (options) { - cancelable = options.cancelable; - } - const segment = this.getSegmentByIdentifier(identifier); - if (!segment) { - return; - } - - if (segment.loader?.executed) { + const { cancelable = true } = options ?? {}; + const segment = this.months.find((segment) => identifier.matches(segment)); + if (!segment || segment.loader?.executed) { return; } const result = await segment.load(cancelable); - if (result === 'LOADED') { + if (result === TaskStatus.LOADED) { updateIntersectionMonthGroup(this, segment); } } - getSegmentByIdentifier(identifier: SegmentIdentifier) { - return this.months.find((segment) => identifier.matches(segment)); - } - getSegmentForAssetId(assetId: string) { for (const month of this.months) { const asset = month.assets.find((asset) => asset.id === assetId); @@ -285,15 +265,6 @@ export abstract class PhotostreamManager { this.updateIntersections(); } - getMaxScrollPercent() { - const totalHeight = this.timelineHeight + this.bottomSectionHeight + this.topSectionHeight; - return (totalHeight - this.viewportHeight) / totalHeight; - } - - getMaxScroll() { - return this.topSectionHeight + this.bottomSectionHeight + (this.timelineHeight - this.viewportHeight); - } - retrieveRange(start: AssetDescriptor, end: AssetDescriptor): Promise { const range: TimelineAsset[] = []; let collecting = false; diff --git a/web/src/lib/managers/photostream-manager/PhotostreamSegment.svelte.ts b/web/src/lib/managers/photostream-manager/PhotostreamSegment.svelte.ts index f78db5db75..1c5e65cdbe 100644 --- a/web/src/lib/managers/photostream-manager/PhotostreamSegment.svelte.ts +++ b/web/src/lib/managers/photostream-manager/PhotostreamSegment.svelte.ts @@ -1,13 +1,13 @@ -import { CancellableTask } from '$lib/utils/cancellable-task'; +import type { PhotostreamManager } from '$lib/managers/photostream-manager/PhotostreamManager.svelte'; +import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; +import type { ViewerAsset } from '$lib/managers/timeline-manager/viewer-asset.svelte'; +import { CancellableTask, TaskStatus } from '$lib/utils/cancellable-task'; import { handleError } from '$lib/utils/handle-error'; import { t } from 'svelte-i18n'; import { get } from 'svelte/store'; -import type { PhotostreamManager } from '$lib/managers/photostream-manager/PhotostreamManager.svelte'; -import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; -import type { ViewerAsset } from '$lib/managers/timeline-manager/viewer-asset.svelte'; - export type SegmentIdentifier = { + id(): string; matches(segment: PhotostreamSegment): boolean; }; export abstract class PhotostreamSegment { @@ -22,10 +22,10 @@ export abstract class PhotostreamSegment { initialCount = $state(0); percent = $state(0); - assetsCount = $derived.by(() => (this.isLoaded ? this.viewerAssets.length : this.initialCount)); + assetsCount = $derived.by(() => (this.loaded ? this.viewerAssets.length : this.initialCount)); loader = new CancellableTask( - () => this.markLoaded(), - () => this.markCanceled, + () => (this.loaded = true), + () => (this.loaded = false), () => this.handleLoadError, ); isHeightActual = $state(false); @@ -34,18 +34,18 @@ export abstract class PhotostreamSegment { abstract get identifier(): SegmentIdentifier; - abstract get id(): string; + abstract get viewerAssets(): ViewerAsset[]; - get isLoaded() { + abstract findAssetAbsolutePosition(assetId: string): number; + + protected abstract fetch(signal: AbortSignal): Promise; + + get loaded() { return this.#isLoaded; } - protected markLoaded() { - this.#isLoaded = true; - } - - protected markCanceled() { - this.#isLoaded = false; + protected set loaded(newValue: boolean) { + this.#isLoaded = newValue; } set intersecting(newValue: boolean) { @@ -65,22 +65,11 @@ export abstract class PhotostreamSegment { return this.#intersecting; } - async load(cancelable: boolean): Promise<'DONE' | 'WAITED' | 'CANCELED' | 'LOADED' | 'ERRORED'> { - return await this.loader?.execute(async (signal: AbortSignal) => { - await this.fetch(signal); - }, cancelable); - } - - protected abstract fetch(signal: AbortSignal): Promise; - get assets(): TimelineAsset[] { return this.#assets; } - abstract get viewerAssets(): ViewerAsset[]; - set height(height: number) { - console.log('height', height); if (this.#height === height) { return; } @@ -131,6 +120,12 @@ export abstract class PhotostreamSegment { return this.#top + this.timelineManager.topSectionHeight; } + async load(cancelable: boolean): Promise { + return await this.loader?.execute(async (signal: AbortSignal) => { + await this.fetch(signal); + }, cancelable); + } + protected handleLoadError(error: unknown) { const _$t = get(t); handleError(error, _$t('errors.failed_to_load_assets')); @@ -146,6 +141,4 @@ export abstract class PhotostreamSegment { this.intersecting = intersecting; this.actuallyIntersecting = actuallyIntersecting; } - - abstract findAssetAbsolutePosition(assetId: string): number; } diff --git a/web/src/lib/managers/timeline-manager/internal/layout-support.svelte.ts b/web/src/lib/managers/timeline-manager/internal/layout-support.svelte.ts index 6b11b8800d..e288b7e6b1 100644 --- a/web/src/lib/managers/timeline-manager/internal/layout-support.svelte.ts +++ b/web/src/lib/managers/timeline-manager/internal/layout-support.svelte.ts @@ -13,7 +13,7 @@ export function updateGeometry( if (invalidateHeight) { month.isHeightActual = false; } - if (!month.isLoaded) { + if (!month.loaded) { const viewportWidth = timelineManager.viewportWidth; if (!month.isHeightActual) { const unwrappedWidth = (3 / 2) * month.assetsCount * timelineManager.rowHeight * (7 / 10); diff --git a/web/src/lib/managers/timeline-manager/month-group.svelte.ts b/web/src/lib/managers/timeline-manager/month-group.svelte.ts index ed6aec9df3..1da1628ade 100644 --- a/web/src/lib/managers/timeline-manager/month-group.svelte.ts +++ b/web/src/lib/managers/timeline-manager/month-group.svelte.ts @@ -1,5 +1,9 @@ -import { AssetOrder, type TimeBucketAssetResponseDto } from '@immich/sdk'; - +import { + PhotostreamSegment, + type SegmentIdentifier, +} from '$lib/managers/photostream-manager/PhotostreamSegment.svelte'; +import { layoutMonthGroup, updateGeometry } from '$lib/managers/timeline-manager/internal/layout-support.svelte'; +import { loadFromTimeBuckets } from '$lib/managers/timeline-manager/internal/load-support.svelte'; import { formatGroupTitle, formatGroupTitleFull, @@ -7,24 +11,16 @@ import { fromTimelinePlainDate, fromTimelinePlainDateTime, fromTimelinePlainYearMonth, - getSegmentIdentifier, getTimes, setDifference, type TimelineDateTime, type TimelineYearMonth, } from '$lib/utils/timeline-util'; - -import { layoutMonthGroup, updateGeometry } from '$lib/managers/timeline-manager/internal/layout-support.svelte'; -import { loadFromTimeBuckets } from '$lib/managers/timeline-manager/internal/load-support.svelte'; - -import { - PhotostreamSegment, - type SegmentIdentifier, -} from '$lib/managers/photostream-manager/PhotostreamSegment.svelte'; +import { AssetOrder, type TimeBucketAssetResponseDto } from '@immich/sdk'; import { SvelteSet } from 'svelte/reactivity'; import { DayGroup } from './day-group.svelte'; import { GroupInsertionCache } from './group-insertion-cache.svelte'; -import type { TimelineManager } from './timeline-manager.svelte'; +import { getSegmentIdentifier, type TimelineManager } from './timeline-manager.svelte'; import type { AssetDescriptor, AssetOperation, Direction, MoveAsset, TimelineAsset } from './types'; import { ViewerAsset } from './viewer-asset.svelte'; @@ -52,9 +48,7 @@ export class MonthGroup extends PhotostreamSegment { this.#timelineManager = timelineManager; this.#sortOrder = order; this.monthGroupTitle = formatMonthGroupTitle(fromTimelinePlainYearMonth(yearMonth)); - if (loaded) { - this.markLoaded(); - } + this.loaded = loaded; } get identifier() { diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts index 2b9ab9dfca..ba37a753a3 100644 --- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts +++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts @@ -1,7 +1,7 @@ import { sdkMock } from '$lib/__mocks__/sdk.mock'; import { getMonthGroupByDate } from '$lib/managers/timeline-manager/internal/search-support.svelte'; import { AbortError } from '$lib/utils'; -import { fromISODateTimeUTCToObject, getSegmentIdentifier } from '$lib/utils/timeline-util'; +import { fromISODateTimeUTCToObject } from '$lib/utils/timeline-util'; import { type AssetResponseDto, type TimeBucketAssetResponseDto } from '@immich/sdk'; import { timelineAssetFactory, toResponseDto } from '@test-data/factories/asset-factory'; import { TimelineManager } from './timeline-manager.svelte'; @@ -22,6 +22,14 @@ function deriveLocalDateTimeFromFileCreatedAt(arg: TimelineAsset): TimelineAsset }; } +const initViewport = async (timelineManager: TimelineManager, viewportHeight = 1000, viewportWidth = 1588) => { + timelineManager.viewportHeight = viewportHeight; + timelineManager.viewportWidth = viewportWidth; + await timelineManager.init(); + timelineManager.updateSlidingWindow(0); + timelineManager.updateIntersections(); +}; + describe('TimelineManager', () => { beforeEach(() => { vi.resetAllMocks(); @@ -63,12 +71,12 @@ describe('TimelineManager', () => { ]); sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssetsResponse[timeBucket])); - await timelineManager.updateViewport({ width: 1588, height: 1000 }); + await initViewport(timelineManager); }); it('should load months in viewport', () => { expect(sdkMock.getTimeBuckets).toBeCalledTimes(1); - expect(sdkMock.getTimeBucket).toHaveBeenCalledTimes(2); + expect(sdkMock.getTimeBucket).toHaveBeenCalledTimes(3); }); it('calculates month height', () => { @@ -82,13 +90,13 @@ describe('TimelineManager', () => { expect.arrayContaining([ expect.objectContaining({ year: 2024, month: 3, height: 165.5 }), expect.objectContaining({ year: 2024, month: 2, height: 11_996 }), - expect.objectContaining({ year: 2024, month: 1, height: 286 }), + expect.objectContaining({ year: 2024, month: 1, height: 404.5 }), ]), ); }); it('calculates timeline height', () => { - expect(timelineManager.timelineHeight).toBe(12_447.5); + expect(timelineManager.timelineHeight).toBe(12566); }); }); @@ -124,19 +132,19 @@ describe('TimelineManager', () => { } return bucketAssetsResponse[timeBucket]; }); - await timelineManager.updateViewport({ width: 1588, height: 0 }); + await initViewport(timelineManager); }); it('loads a month', async () => { expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 1 })?.assets.length).toEqual(0); await timelineManager.loadSegment(getSegmentIdentifier({ year: 2024, month: 1 })); - expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + expect(sdkMock.getTimeBucket).toBeCalledTimes(2); expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 1 })?.assets.length).toEqual(3); }); it('ignores invalid months', async () => { await timelineManager.loadSegment(getSegmentIdentifier({ year: 2023, month: 1 })); - expect(sdkMock.getTimeBucket).toBeCalledTimes(0); + expect(sdkMock.getTimeBucket).toBeCalledTimes(2); }); it('cancels month loading', async () => { @@ -154,10 +162,10 @@ describe('TimelineManager', () => { timelineManager.loadSegment(getSegmentIdentifier({ year: 2024, month: 1 })), timelineManager.loadSegment(getSegmentIdentifier({ year: 2024, month: 1 })), ]); - expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + expect(sdkMock.getTimeBucket).toBeCalledTimes(2); await timelineManager.loadSegment(getSegmentIdentifier({ year: 2024, month: 1 })); - expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + expect(sdkMock.getTimeBucket).toBeCalledTimes(2); }); it('allows loading a canceled month', async () => { @@ -180,7 +188,8 @@ describe('TimelineManager', () => { timelineManager = new TimelineManager(); sdkMock.getTimeBuckets.mockResolvedValue([]); - await timelineManager.updateViewport({ width: 1588, height: 1000 }); + timelineManager.viewportHeight = 1000; + timelineManager.viewportHeight = 1588; }); it('is empty initially', () => { @@ -304,7 +313,8 @@ describe('TimelineManager', () => { timelineManager = new TimelineManager(); sdkMock.getTimeBuckets.mockResolvedValue([]); - await timelineManager.updateViewport({ width: 1588, height: 1000 }); + timelineManager.viewportHeight = 1000; + timelineManager.viewportHeight = 1588; }); it('ignores non-existing assets', () => { @@ -359,7 +369,8 @@ describe('TimelineManager', () => { timelineManager = new TimelineManager(); sdkMock.getTimeBuckets.mockResolvedValue([]); - await timelineManager.updateViewport({ width: 1588, height: 1000 }); + timelineManager.viewportHeight = 1000; + timelineManager.viewportHeight = 1588; }); it('ignores invalid IDs', () => { @@ -411,7 +422,8 @@ describe('TimelineManager', () => { beforeEach(async () => { timelineManager = new TimelineManager(); sdkMock.getTimeBuckets.mockResolvedValue([]); - await timelineManager.updateViewport({ width: 0, height: 0 }); + + await initViewport(timelineManager, 0, 0); }); it('empty store returns null', () => { @@ -468,7 +480,8 @@ describe('TimelineManager', () => { { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, ]); sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssetsResponse[timeBucket])); - await timelineManager.updateViewport({ width: 1588, height: 1000 }); + + initViewport(timelineManager); }); it('returns null for invalid assetId', async () => { @@ -535,7 +548,7 @@ describe('TimelineManager', () => { timelineManager = new TimelineManager(); sdkMock.getTimeBuckets.mockResolvedValue([]); - await timelineManager.updateViewport({ width: 0, height: 0 }); + await initViewport(timelineManager, 0, 0); }); it('returns null for invalid months', () => { @@ -618,7 +631,7 @@ describe('TimelineManager', () => { ]); sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssetsResponse[timeBucket])); - await timelineManager.updateViewport({ width: 1588, height: 0 }); + await initViewport(timelineManager); }); it('gets all assets once', async () => { diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts index 79c000b9c1..7da0bcf5a5 100644 --- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts +++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts @@ -3,12 +3,7 @@ import { AssetOrder, getAssetInfo, getTimeBuckets } from '@immich/sdk'; import { authManager } from '$lib/managers/auth-manager.svelte'; import { CancellableTask } from '$lib/utils/cancellable-task'; -import { - getSegmentIdentifier, - toTimelineAsset, - type TimelineDateTime, - type TimelineYearMonth, -} from '$lib/utils/timeline-util'; +import { toTimelineAsset, type TimelineDateTime, type TimelineYearMonth } from '$lib/utils/timeline-util'; import { isEqual } from 'lodash-es'; import { SvelteDate, SvelteMap, SvelteSet } from 'svelte/reactivity'; @@ -39,6 +34,17 @@ import type { TimelineManagerOptions, } from './types'; +export const getSegmentIdentifier = (yearMonth: TimelineYearMonth | TimelineDateTime) => ({ + id: () => { + return yearMonth.year + '-' + yearMonth.month; + }, + matches: (segment: MonthGroup) => { + return ( + segment.yearMonth && segment.yearMonth.year === yearMonth.year && segment.yearMonth.month === yearMonth.month + ); + }, +}); + export class TimelineManager extends PhotostreamManager { albumAssets: Set = new SvelteSet(); scrubberMonths: ScrubberMonth[] = $state([]); diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts index e9ae7931f2..f4954b86d4 100644 --- a/web/src/lib/utils/asset-utils.ts +++ b/web/src/lib/utils/asset-utils.ts @@ -513,7 +513,7 @@ export const selectAllAssets = async (timelineManager: TimelineManager, assetInt try { for (const monthGroup of timelineManager.months) { - await timelineManager.loadSegment(monthGroup.identifier); + await monthGroup.load(false); if (!get(isSelectingAllAssets)) { assetInteraction.clearMultiselect(); diff --git a/web/src/lib/utils/cancellable-task.ts b/web/src/lib/utils/cancellable-task.ts index cf6335977a..f05603bb4c 100644 --- a/web/src/lib/utils/cancellable-task.ts +++ b/web/src/lib/utils/cancellable-task.ts @@ -1,3 +1,10 @@ +export enum TaskStatus { + DONE, + WAITED, + CANCELED, + LOADED, + ERRORED, +} export class CancellableTask { cancelToken: AbortController | null = null; cancellable: boolean = true; @@ -32,18 +39,18 @@ export class CancellableTask { async waitUntilCompletion() { if (this.executed) { - return 'DONE'; + return TaskStatus.DONE; } // if there is a cancel token, task is currently executing, so wait on the promise. If it // isn't, then the task is in new state, it hasn't been loaded, nor has it been executed. // in either case, we wait on the promise. await this.complete; - return 'WAITED'; + return TaskStatus.WAITED; } async execute Promise>(f: F, cancellable: boolean) { if (this.executed) { - return 'DONE'; + return TaskStatus.DONE; } // if promise is pending, wait on previous request instead. @@ -54,7 +61,7 @@ export class CancellableTask { this.cancellable = cancellable; } await this.complete; - return 'WAITED'; + return TaskStatus.WAITED; } this.cancellable = cancellable; const cancelToken = (this.cancelToken = new AbortController()); @@ -62,18 +69,18 @@ export class CancellableTask { try { await f(cancelToken.signal); if (cancelToken.signal.aborted) { - return 'CANCELED'; + return TaskStatus.CANCELED; } this.#transitionToExecuted(); - return 'LOADED'; + return TaskStatus.LOADED; } catch (error) { // eslint-disable-next-line @typescript-eslint/no-explicit-any if ((error as any).name === 'AbortError') { // abort error is not treated as an error, but as a cancellation. - return 'CANCELED'; + return TaskStatus.CANCELED; } this.#transitionToErrored(error); - return 'ERRORED'; + return TaskStatus.ERRORED; } finally { this.cancelToken = null; } diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts index 0a25040510..79331cf534 100644 --- a/web/src/lib/utils/timeline-util.ts +++ b/web/src/lib/utils/timeline-util.ts @@ -1,4 +1,3 @@ -import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte'; import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; import { locale } from '$lib/stores/preferences.store'; import { getAssetRatio } from '$lib/utils/asset-utils'; @@ -243,11 +242,3 @@ export function setDifference(setA: Set, setB: Set): SvelteSet { } return result; } - -export const getSegmentIdentifier = (yearMonth: TimelineYearMonth | TimelineDateTime) => ({ - matches(segment: MonthGroup) { - return ( - segment.yearMonth && segment.yearMonth.year === yearMonth.year && segment.yearMonth.month === yearMonth.month - ); - }, -});