|
10 | 10 | import { AppRoute, AssetAction, ProjectionType } from '$lib/constants'; |
11 | 11 | import { activityManager } from '$lib/managers/activity-manager.svelte'; |
12 | 12 | import { authManager } from '$lib/managers/auth-manager.svelte'; |
13 | | - import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; |
| 13 | + import { preloadManager } from '$lib/managers/PreloadManager.svelte'; |
14 | 14 | import { closeEditorCofirm } from '$lib/stores/asset-editor.store'; |
15 | 15 | import { assetViewingStore } from '$lib/stores/asset-viewing.store'; |
16 | 16 | import { ocrManager } from '$lib/stores/ocr.svelte'; |
17 | 17 | import { alwaysLoadOriginalVideo, isShowDetail } from '$lib/stores/preferences.store'; |
18 | 18 | import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; |
19 | 19 | import { user } from '$lib/stores/user.store'; |
20 | 20 | import { websocketEvents } from '$lib/stores/websocket'; |
21 | | - import { getAssetJobMessage, getSharedLink, handlePromiseError } from '$lib/utils'; |
| 21 | + import { getAssetJobMessage, getAssetUrl, getSharedLink, handlePromiseError } from '$lib/utils'; |
22 | 22 | import { handleError } from '$lib/utils/handle-error'; |
| 23 | + import { InvocationTracker } from '$lib/utils/invocationTracker'; |
23 | 24 | import { SlideshowHistory } from '$lib/utils/slideshow-history'; |
| 25 | + import { preloadImageUrl } from '$lib/utils/sw-messaging'; |
24 | 26 | import { toTimelineAsset } from '$lib/utils/timeline-util'; |
25 | 27 | import { |
26 | 28 | AssetJobName, |
|
52 | 54 |
|
53 | 55 | type HasAsset = boolean; |
54 | 56 |
|
| 57 | + export type AssetCursor = { |
| 58 | + current: AssetResponseDto; |
| 59 | + nextAsset: AssetResponseDto | undefined | null; |
| 60 | + previousAsset: AssetResponseDto | undefined | null; |
| 61 | + }; |
| 62 | +
|
55 | 63 | interface Props { |
56 | | - asset: AssetResponseDto; |
57 | | - preloadAssets?: TimelineAsset[]; |
| 64 | + cursor: AssetCursor; |
58 | 65 | showNavigation?: boolean; |
59 | 66 | withStacked?: boolean; |
60 | 67 | isShared?: boolean; |
|
71 | 78 | } |
72 | 79 |
|
73 | 80 | let { |
74 | | - asset = $bindable(), |
75 | | - preloadAssets = $bindable([]), |
| 81 | + cursor, |
76 | 82 | showNavigation = true, |
77 | 83 | withStacked = false, |
78 | 84 | isShared = false, |
|
99 | 105 | const stackThumbnailSize = 60; |
100 | 106 | const stackSelectedThumbnailSize = 65; |
101 | 107 |
|
| 108 | + let asset = $derived(cursor.current); |
102 | 109 | let appearsInAlbums: AlbumResponseDto[] = $state([]); |
103 | 110 | let shouldPlayMotionPhoto = $state(false); |
104 | 111 | let sharedLink = getSharedLink(); |
105 | | - let enableDetailPanel = asset.hasMetadata; |
| 112 | + let enableDetailPanel = $derived(asset.hasMetadata); |
106 | 113 | let slideshowStateUnsubscribe: () => void; |
107 | 114 | let shuffleSlideshowUnsubscribe: () => void; |
108 | 115 | let previewStackedAsset: AssetResponseDto | undefined = $state(); |
|
135 | 142 |
|
136 | 143 | untrack(() => { |
137 | 144 | if (stack && stack?.assets.length > 1) { |
138 | | - preloadAssets.push(toTimelineAsset(stack.assets[1])); |
| 145 | + preloadImageUrl(getAssetUrl({ asset: stack.assets[1] })); |
139 | 146 | } |
140 | 147 | }); |
141 | 148 | }; |
|
234 | 241 | }); |
235 | 242 | }; |
236 | 243 |
|
237 | | - const navigateAsset = async (order?: 'previous' | 'next', e?: Event) => { |
| 244 | + const tracker = new InvocationTracker(); |
| 245 | +
|
| 246 | + const navigateAsset = (order?: 'previous' | 'next', e?: Event) => { |
238 | 247 | if (!order) { |
239 | 248 | if ($slideshowState === SlideshowState.PlaySlideshow) { |
240 | 249 | order = $slideshowNavigation === SlideshowNavigation.AscendingOrder ? 'previous' : 'next'; |
|
244 | 253 | } |
245 | 254 |
|
246 | 255 | e?.stopPropagation(); |
| 256 | + preloadManager.cancel(asset); |
| 257 | + if (tracker.isActive()) { |
| 258 | + return; |
| 259 | + } |
247 | 260 |
|
248 | | - let hasNext = false; |
249 | | -
|
250 | | - if ($slideshowState === SlideshowState.PlaySlideshow && $slideshowNavigation === SlideshowNavigation.Shuffle) { |
251 | | - hasNext = order === 'previous' ? slideshowHistory.previous() : slideshowHistory.next(); |
252 | | - if (!hasNext) { |
253 | | - const asset = await onRandom(); |
254 | | - if (asset) { |
255 | | - slideshowHistory.queue(asset); |
256 | | - hasNext = true; |
| 261 | + void tracker.invoke(async () => { |
| 262 | + let hasNext = false; |
| 263 | +
|
| 264 | + if ($slideshowState === SlideshowState.PlaySlideshow && $slideshowNavigation === SlideshowNavigation.Shuffle) { |
| 265 | + hasNext = order === 'previous' ? slideshowHistory.previous() : slideshowHistory.next(); |
| 266 | + if (!hasNext) { |
| 267 | + const asset = await onRandom(); |
| 268 | + if (asset) { |
| 269 | + slideshowHistory.queue(asset); |
| 270 | + hasNext = true; |
| 271 | + } |
257 | 272 | } |
| 273 | + } else { |
| 274 | + hasNext = order === 'previous' ? await onPrevious() : await onNext(); |
258 | 275 | } |
259 | | - } else { |
260 | | - hasNext = order === 'previous' ? await onPrevious() : await onNext(); |
261 | | - } |
262 | 276 |
|
263 | | - if ($slideshowState === SlideshowState.PlaySlideshow) { |
264 | | - if (hasNext) { |
265 | | - $restartSlideshowProgress = true; |
266 | | - } else { |
267 | | - await handleStopSlideshow(); |
| 277 | + if ($slideshowState === SlideshowState.PlaySlideshow) { |
| 278 | + if (hasNext) { |
| 279 | + $restartSlideshowProgress = true; |
| 280 | + } else { |
| 281 | + await handleStopSlideshow(); |
| 282 | + } |
268 | 283 | } |
269 | | - } |
| 284 | + }); |
270 | 285 | }; |
271 | 286 |
|
272 | | - // const showEditorHandler = () => { |
273 | | - // if (isShowActivity) { |
274 | | - // isShowActivity = false; |
275 | | - // } |
276 | | - // isShowEditor = !isShowEditor; |
277 | | - // }; |
278 | | -
|
279 | 287 | const handleRunJob = async (name: AssetJobName) => { |
280 | 288 | try { |
281 | 289 | await runAssetJobs({ assetJobsDto: { assetIds: [asset.id], name } }); |
|
378 | 386 |
|
379 | 387 | let isFullScreen = $derived(fullscreenElement !== null); |
380 | 388 |
|
381 | | - $effect(() => { |
382 | | - if (asset) { |
383 | | - previewStackedAsset = undefined; |
384 | | - handlePromiseError(refreshStack()); |
385 | | - } |
386 | | - }); |
387 | 389 | $effect(() => { |
388 | 390 | if (album && !album.isActivityEnabled && activityManager.commentCount === 0) { |
389 | 391 | isShowActivity = false; |
|
395 | 397 | } |
396 | 398 | }); |
397 | 399 |
|
398 | | - // primarily, this is reactive on `asset` |
399 | | - $effect(() => { |
400 | | - handlePromiseError(handleGetAllAlbums()); |
| 400 | + const refresh = async () => { |
| 401 | + await refreshStack(); |
| 402 | + await handleGetAllAlbums(); |
401 | 403 | ocrManager.clear(); |
402 | 404 | if (!sharedLink) { |
403 | | - handlePromiseError(ocrManager.getAssetOcr(asset.id)); |
| 405 | + if (previewStackedAsset) { |
| 406 | + await ocrManager.getAssetOcr(previewStackedAsset.id); |
| 407 | + } |
| 408 | + await ocrManager.getAssetOcr(asset.id); |
404 | 409 | } |
| 410 | + }; |
| 411 | +
|
| 412 | + $effect(() => { |
| 413 | + // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 414 | + asset; |
| 415 | + untrack(() => handlePromiseError(refresh())); |
| 416 | + preloadManager.preload(cursor.nextAsset); |
| 417 | + preloadManager.preload(cursor.previousAsset); |
405 | 418 | }); |
406 | 419 | </script> |
407 | 420 |
|
|
473 | 486 | <PhotoViewer |
474 | 487 | bind:zoomToggle |
475 | 488 | bind:copyImage |
476 | | - asset={previewStackedAsset} |
477 | | - {preloadAssets} |
| 489 | + cursor={{ ...cursor, current: previewStackedAsset }} |
478 | 490 | onPreviousAsset={() => navigateAsset('previous')} |
479 | 491 | onNextAsset={() => navigateAsset('next')} |
480 | 492 | haveFadeTransition={false} |
|
519 | 531 | <PhotoViewer |
520 | 532 | bind:zoomToggle |
521 | 533 | bind:copyImage |
522 | | - {asset} |
523 | | - {preloadAssets} |
| 534 | + {cursor} |
524 | 535 | onPreviousAsset={() => navigateAsset('previous')} |
525 | 536 | onNextAsset={() => navigateAsset('next')} |
526 | 537 | {sharedLink} |
|
0 commit comments