mirror of
https://github.com/immich-app/immich.git
synced 2025-12-17 17:23:20 +03:00
Run ops even if asset no longer matches criteria; add tests
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
|
import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
|
||||||
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
|
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
|
||||||
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
||||||
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
import { assetSnapshot, assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
|
import { assetSnapshot, assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
|
||||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TUNABLES } from '$lib/utils/tunables';
|
import { TUNABLES } from '$lib/utils/tunables';
|
||||||
import type { MonthGroup } from '../month-group.svelte';
|
import type { MonthGroup } from '../month-group.svelte';
|
||||||
import type { TimelineManager } from '../timeline-manager.svelte';
|
import { TimelineManager } from '../timeline-manager.svelte';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
TIMELINE: { INTERSECTION_EXPAND_TOP, INTERSECTION_EXPAND_BOTTOM },
|
TIMELINE: { INTERSECTION_EXPAND_TOP, INTERSECTION_EXPAND_BOTTOM },
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { MonthGroup } from '../month-group.svelte';
|
import type { MonthGroup } from '../month-group.svelte';
|
||||||
import type { TimelineManager } from '../timeline-manager.svelte';
|
import { TimelineManager } from '../timeline-manager.svelte';
|
||||||
import type { UpdateGeometryOptions } from '../types';
|
import type { UpdateGeometryOptions } from '../types';
|
||||||
|
|
||||||
export function updateGeometry(timelineManager: TimelineManager, month: MonthGroup, options: UpdateGeometryOptions) {
|
export function updateGeometry(timelineManager: TimelineManager, month: MonthGroup, options: UpdateGeometryOptions) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { authManager } from '$lib/managers/auth-manager.svelte';
|
|||||||
import { toISOYearMonthUTC } from '$lib/utils/timeline-util';
|
import { toISOYearMonthUTC } from '$lib/utils/timeline-util';
|
||||||
import { getTimeBucket } from '@immich/sdk';
|
import { getTimeBucket } from '@immich/sdk';
|
||||||
import type { MonthGroup } from '../month-group.svelte';
|
import type { MonthGroup } from '../month-group.svelte';
|
||||||
import type { TimelineManager } from '../timeline-manager.svelte';
|
import { TimelineManager } from '../timeline-manager.svelte';
|
||||||
import type { TimelineManagerOptions } from '../types';
|
import type { TimelineManagerOptions } from '../types';
|
||||||
|
|
||||||
export async function loadFromTimeBuckets(
|
export async function loadFromTimeBuckets(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { plainDateTimeCompare, type TimelineYearMonth } from '$lib/utils/timelin
|
|||||||
import { AssetOrder } from '@immich/sdk';
|
import { AssetOrder } from '@immich/sdk';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import type { MonthGroup } from '../month-group.svelte';
|
import type { MonthGroup } from '../month-group.svelte';
|
||||||
import type { TimelineManager } from '../timeline-manager.svelte';
|
import { TimelineManager } from '../timeline-manager.svelte';
|
||||||
import type { AssetDescriptor, Direction, TimelineAsset } from '../types';
|
import type { AssetDescriptor, Direction, TimelineAsset } from '../types';
|
||||||
|
|
||||||
export async function getAssetWithOffset(
|
export async function getAssetWithOffset(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { PendingChange, TimelineAsset } from '$lib/managers/timeline-manager/types';
|
import type { PendingChange, TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
import { websocketEvents } from '$lib/stores/websocket';
|
import { websocketEvents } from '$lib/stores/websocket';
|
||||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { get } from 'svelte/store';
|
|||||||
import { onCreateMonthGroup } from '$lib/managers/timeline-manager/internal/TestHooks.svelte';
|
import { onCreateMonthGroup } from '$lib/managers/timeline-manager/internal/TestHooks.svelte';
|
||||||
import { DayGroup } from './day-group.svelte';
|
import { DayGroup } from './day-group.svelte';
|
||||||
import { GroupInsertionCache } from './group-insertion-cache.svelte';
|
import { GroupInsertionCache } from './group-insertion-cache.svelte';
|
||||||
import type { TimelineManager } from './timeline-manager.svelte';
|
import { TimelineManager } from './timeline-manager.svelte';
|
||||||
import type { AssetDescriptor, AssetOperation, Direction, TimelineAsset } from './types';
|
import type { AssetDescriptor, AssetOperation, Direction, TimelineAsset } from './types';
|
||||||
import { ViewerAsset } from './viewer-asset.svelte';
|
import { ViewerAsset } from './viewer-asset.svelte';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { setTestHooks } from '$lib/managers/timeline-manager/internal/TestHooks.
|
|||||||
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
||||||
import { AbortError } from '$lib/utils';
|
import { AbortError } from '$lib/utils';
|
||||||
import { fromISODateTimeUTCToObject } from '$lib/utils/timeline-util';
|
import { fromISODateTimeUTCToObject } from '$lib/utils/timeline-util';
|
||||||
import { type AssetResponseDto, type TimeBucketAssetResponseDto } from '@immich/sdk';
|
import { AssetVisibility, type AssetResponseDto, type TimeBucketAssetResponseDto } from '@immich/sdk';
|
||||||
import { timelineAssetFactory, toResponseDto } from '@test-data/factories/asset-factory';
|
import { timelineAssetFactory, toResponseDto } from '@test-data/factories/asset-factory';
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
import type { MockInstance } from 'vitest';
|
import type { MockInstance } from 'vitest';
|
||||||
@@ -465,6 +465,69 @@ describe('TimelineManager', () => {
|
|||||||
expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 3 })).not.toBeUndefined();
|
expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 3 })).not.toBeUndefined();
|
||||||
expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 3 })?.getAssets().length).toEqual(1);
|
expect(getMonthGroupByDate(timelineManager, { year: 2024, month: 3 })?.getAssets().length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('asset is removed during upsert when TimelineManager if visibility changes', async () => {
|
||||||
|
await timelineManager.updateOptions({
|
||||||
|
visibility: AssetVisibility.Archive,
|
||||||
|
});
|
||||||
|
const fixture = deriveLocalDateTimeFromFileCreatedAt(
|
||||||
|
timelineAssetFactory.build({
|
||||||
|
visibility: AssetVisibility.Archive,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([fixture]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
|
||||||
|
const updated = Object.freeze({ ...fixture, visibility: AssetVisibility.Timeline });
|
||||||
|
timelineManager.upsertAssets([updated]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(0);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([{ ...fixture, visibility: AssetVisibility.Archive }]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('asset is removed during upsert when TimelineManager if isFavorite changes', async () => {
|
||||||
|
await timelineManager.updateOptions({
|
||||||
|
isFavorite: true,
|
||||||
|
});
|
||||||
|
const fixture = deriveLocalDateTimeFromFileCreatedAt(
|
||||||
|
timelineAssetFactory.build({
|
||||||
|
isFavorite: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([fixture]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
|
||||||
|
const updated = Object.freeze({ ...fixture, isFavorite: false });
|
||||||
|
timelineManager.upsertAssets([updated]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(0);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([{ ...fixture, isFavorite: true }]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('asset is removed during upsert when TimelineManager if isTrashed changes', async () => {
|
||||||
|
await timelineManager.updateOptions({
|
||||||
|
isTrashed: true,
|
||||||
|
});
|
||||||
|
const fixture = deriveLocalDateTimeFromFileCreatedAt(
|
||||||
|
timelineAssetFactory.build({
|
||||||
|
isTrashed: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([fixture]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
|
||||||
|
const updated = Object.freeze({ ...fixture, isTrashed: false });
|
||||||
|
timelineManager.upsertAssets([updated]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(0);
|
||||||
|
|
||||||
|
timelineManager.upsertAssets([{ ...fixture, isTrashed: true }]);
|
||||||
|
expect(timelineManager.assetCount).toEqual(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeAssets', () => {
|
describe('removeAssets', () => {
|
||||||
|
|||||||
@@ -323,9 +323,9 @@ export class TimelineManager extends VirtualScrollManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
upsertAssets(assets: TimelineAsset[]) {
|
upsertAssets(assets: TimelineAsset[]) {
|
||||||
const notExcluded = assets.filter((asset) => !this.isExcluded(asset));
|
const notUpdated = this.#updateAssets(assets);
|
||||||
const notUpdated = this.#updateAssets(notExcluded);
|
const notExcluded = notUpdated.filter((asset) => !this.isExcluded(asset));
|
||||||
this.addAssetsToSegments(notUpdated);
|
this.addAssetsToSegments(notExcluded);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findMonthGroupForAsset(id: string) {
|
async findMonthGroupForAsset(id: string) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import DateInput from '$lib/elements/DateInput.svelte';
|
import DateInput from '$lib/elements/DateInput.svelte';
|
||||||
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
import { getPreferredTimeZone, getTimezones, toDatetime, type ZoneOption } from '$lib/modals/timezone-utils';
|
import { getPreferredTimeZone, getTimezones, toDatetime, type ZoneOption } from '$lib/modals/timezone-utils';
|
||||||
import { Button, HStack, Modal, ModalBody, ModalFooter, VStack } from '@immich/ui';
|
import { Button, HStack, Modal, ModalBody, ModalFooter, VStack } from '@immich/ui';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import ToastAction from '$lib/components/ToastAction.svelte';
|
|||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||||
import { downloadManager } from '$lib/managers/download-manager.svelte';
|
import { downloadManager } from '$lib/managers/download-manager.svelte';
|
||||||
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
import { assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
|
import { assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
|
||||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
|
|||||||
Reference in New Issue
Block a user