mirror of
https://github.com/immich-app/immich.git
synced 2025-12-17 09:13:17 +03:00
Compare commits
1 Commits
refactor-l
...
push-qvukt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58e169b969 |
@@ -13,7 +13,12 @@
|
|||||||
import { isIntersecting } from '$lib/managers/timeline-manager/internal/intersection-support.svelte';
|
import { isIntersecting } from '$lib/managers/timeline-manager/internal/intersection-support.svelte';
|
||||||
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
|
||||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { TimelineAsset, TimelineManagerOptions, ViewportTopMonth } from '$lib/managers/timeline-manager/types';
|
import {
|
||||||
|
ExtendedTimelineManager,
|
||||||
|
type TimelineAsset,
|
||||||
|
type TimelineManagerOptions,
|
||||||
|
type ViewportTopMonth,
|
||||||
|
} 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';
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
@@ -90,7 +95,7 @@
|
|||||||
onThumbnailClick,
|
onThumbnailClick,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
timelineManager = new TimelineManager();
|
timelineManager = new ExtendedTimelineManager();
|
||||||
onDestroy(() => timelineManager.destroy());
|
onDestroy(() => timelineManager.destroy());
|
||||||
$effect(() => options && void timelineManager.updateOptions(options));
|
$effect(() => options && void timelineManager.updateOptions(options));
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,36 @@
|
|||||||
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import type { GenericTimeManager, 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';
|
||||||
import { throttle } from 'lodash-es';
|
import { throttle } from 'lodash-es';
|
||||||
import type { Unsubscriber } from 'svelte/store';
|
import type { Unsubscriber } from 'svelte/store';
|
||||||
|
|
||||||
export class WebsocketSupport {
|
export function HasWebsocket<T extends GenericTimeManager>(timelineManager: T) {
|
||||||
|
return class extends timelineManager {
|
||||||
#pendingChanges: PendingChange[] = [];
|
#pendingChanges: PendingChange[] = [];
|
||||||
#unsubscribers: Unsubscriber[] = [];
|
#unsubscribers: Unsubscriber[] = [];
|
||||||
#timelineManager: TimelineManager;
|
|
||||||
|
|
||||||
#processPendingChanges = throttle(() => {
|
#processPendingChanges = throttle(() => {
|
||||||
const { add, update, remove } = this.#getPendingChangeBatches();
|
const { add, update, remove } = this.#getPendingChangeBatches();
|
||||||
if (add.length > 0) {
|
if (add.length > 0) {
|
||||||
this.#timelineManager.upsertAssets(add);
|
this.upsertAssets(add);
|
||||||
}
|
}
|
||||||
if (update.length > 0) {
|
if (update.length > 0) {
|
||||||
this.#timelineManager.upsertAssets(update);
|
this.upsertAssets(update);
|
||||||
}
|
}
|
||||||
if (remove.length > 0) {
|
if (remove.length > 0) {
|
||||||
this.#timelineManager.removeAssets(remove);
|
this.removeAssets(remove);
|
||||||
}
|
}
|
||||||
this.#pendingChanges = [];
|
this.#pendingChanges = [];
|
||||||
}, 2500);
|
}, 2500);
|
||||||
|
|
||||||
constructor(timeineManager: TimelineManager) {
|
override connect(): void {
|
||||||
this.#timelineManager = timeineManager;
|
super.connect();
|
||||||
|
if (this.#unsubscribers.length !== 0) {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
throw new Error('Websocket already connected');
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectWebsocketEvents() {
|
|
||||||
this.#unsubscribers.push(
|
this.#unsubscribers.push(
|
||||||
websocketEvents.on('on_upload_success', (asset) =>
|
websocketEvents.on('on_upload_success', (asset) =>
|
||||||
this.#addPendingChanges({ type: 'add', values: [toTimelineAsset(asset)] }),
|
this.#addPendingChanges({ type: 'add', values: [toTimelineAsset(asset)] }),
|
||||||
@@ -37,15 +39,18 @@ export class WebsocketSupport {
|
|||||||
websocketEvents.on('on_asset_update', (asset) =>
|
websocketEvents.on('on_asset_update', (asset) =>
|
||||||
this.#addPendingChanges({ type: 'update', values: [toTimelineAsset(asset)] }),
|
this.#addPendingChanges({ type: 'update', values: [toTimelineAsset(asset)] }),
|
||||||
),
|
),
|
||||||
websocketEvents.on('on_asset_delete', (id: string) => this.#addPendingChanges({ type: 'delete', values: [id] })),
|
websocketEvents.on('on_asset_delete', (id: string) =>
|
||||||
|
this.#addPendingChanges({ type: 'delete', values: [id] }),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectWebsocketEvents() {
|
override disconnect(): void {
|
||||||
for (const unsubscribe of this.#unsubscribers) {
|
for (const unsubscribe of this.#unsubscribers) {
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
}
|
}
|
||||||
this.#unsubscribers = [];
|
this.#unsubscribers = [];
|
||||||
|
super.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
#addPendingChanges(...changes: PendingChange[]) {
|
#addPendingChanges(...changes: PendingChange[]) {
|
||||||
@@ -82,4 +87,5 @@ export class WebsocketSupport {
|
|||||||
}
|
}
|
||||||
return batch;
|
return batch;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
getMonthGroupByDate,
|
getMonthGroupByDate,
|
||||||
retrieveRange as retrieveRangeUtil,
|
retrieveRange as retrieveRangeUtil,
|
||||||
} from '$lib/managers/timeline-manager/internal/search-support.svelte';
|
} from '$lib/managers/timeline-manager/internal/search-support.svelte';
|
||||||
import { WebsocketSupport } from '$lib/managers/timeline-manager/internal/websocket-support.svelte';
|
|
||||||
import { CancellableTask } from '$lib/utils/cancellable-task';
|
import { CancellableTask } from '$lib/utils/cancellable-task';
|
||||||
import { toTimelineAsset, type TimelineDateTime, type TimelineYearMonth } from '$lib/utils/timeline-util';
|
import { toTimelineAsset, type TimelineDateTime, type TimelineYearMonth } from '$lib/utils/timeline-util';
|
||||||
import { AssetOrder, getAssetInfo, getTimeBuckets } from '@immich/sdk';
|
import { AssetOrder, getAssetInfo, getTimeBuckets } from '@immich/sdk';
|
||||||
@@ -84,7 +83,6 @@ export class TimelineManager extends VirtualScrollManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static #INIT_OPTIONS = {};
|
static #INIT_OPTIONS = {};
|
||||||
#websocketSupport: WebsocketSupport | undefined;
|
|
||||||
#options: TimelineManagerOptions = TimelineManager.#INIT_OPTIONS;
|
#options: TimelineManagerOptions = TimelineManager.#INIT_OPTIONS;
|
||||||
#updatingIntersections = false;
|
#updatingIntersections = false;
|
||||||
#scrollableElement: HTMLElement | undefined = $state();
|
#scrollableElement: HTMLElement | undefined = $state();
|
||||||
@@ -140,21 +138,9 @@ export class TimelineManager extends VirtualScrollManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {}
|
||||||
if (this.#websocketSupport) {
|
|
||||||
throw new Error('TimelineManager already connected');
|
|
||||||
}
|
|
||||||
this.#websocketSupport = new WebsocketSupport(this);
|
|
||||||
this.#websocketSupport.connectWebsocketEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {}
|
||||||
if (!this.#websocketSupport) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.#websocketSupport.disconnectWebsocketEvents();
|
|
||||||
this.#websocketSupport = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculateMonthBottomViewportRatio(month: MonthGroup | undefined) {
|
#calculateMonthBottomViewportRatio(month: MonthGroup | undefined) {
|
||||||
if (!month) {
|
if (!month) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { HasWebsocket } from '$lib/managers/timeline-manager/internal/websocket-support.svelte';
|
||||||
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import type { TimelineDate, TimelineDateTime, TimelineYearMonth } from '$lib/utils/timeline-util';
|
import type { TimelineDate, TimelineDateTime, TimelineYearMonth } from '$lib/utils/timeline-util';
|
||||||
import type { AssetStackResponseDto, AssetVisibility } from '@immich/sdk';
|
import type { AssetStackResponseDto, AssetVisibility } from '@immich/sdk';
|
||||||
|
|
||||||
@@ -96,3 +98,8 @@ export interface UpdateGeometryOptions {
|
|||||||
invalidateHeight: boolean;
|
invalidateHeight: boolean;
|
||||||
noDefer?: boolean;
|
noDefer?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
type GenericConstructor<T = {}> = new (...args: any[]) => T;
|
||||||
|
export type GenericTimeManager = GenericConstructor<TimelineManager>;
|
||||||
|
export const ExtendedTimelineManager = HasWebsocket(TimelineManager);
|
||||||
|
|||||||
Reference in New Issue
Block a user