diff --git a/web/src/lib/components/asset-viewer/video-native-viewer.svelte b/web/src/lib/components/asset-viewer/video-native-viewer.svelte
index 8205c8c353..4b8bb40f77 100644
--- a/web/src/lib/components/asset-viewer/video-native-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/video-native-viewer.svelte
@@ -2,6 +2,7 @@
import FaceEditor from '$lib/components/asset-viewer/face-editor/face-editor.svelte';
import VideoRemoteViewer from '$lib/components/asset-viewer/video-remote-viewer.svelte';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
+ import { assetViewerFadeDuration } from '$lib/constants';
import { castManager } from '$lib/managers/cast-manager.svelte';
import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { loopVideo as loopVideoPreference, videoViewerMuted, videoViewerVolume } from '$lib/stores/preferences.store';
@@ -41,8 +42,11 @@
let assetFileUrl = $state('');
let forceMuted = $state(false);
let isScrubbing = $state(false);
+ let showVideo = $state(false);
onMount(() => {
+ // Show video after mount to ensure fading in.
+ showVideo = true;
assetFileUrl = getAssetPlaybackUrl({ id: assetId, cacheKey });
if (videoPlayer) {
forceMuted = false;
@@ -102,59 +106,61 @@
});
-
- {#if castManager.isCasting}
-
-
-
- {:else}
-
-
- {#if isLoading}
-
-
+{#if showVideo}
+
+ {#if castManager.isCasting}
+
+
- {/if}
+ {:else}
+
- {#if isFaceEditMode.value}
-
+ {#if isLoading}
+
+
+
+ {/if}
+
+ {#if isFaceEditMode.value}
+
+ {/if}
{/if}
- {/if}
-
+
+{/if}
diff --git a/web/src/lib/components/memory-page/memory-photo-viewer.svelte b/web/src/lib/components/memory-page/memory-photo-viewer.svelte
new file mode 100644
index 0000000000..b0b1dc98a6
--- /dev/null
+++ b/web/src/lib/components/memory-page/memory-photo-viewer.svelte
@@ -0,0 +1,69 @@
+
+
+{#if !imageLoaded}
+
+

+{/if}
+
+{#if !imageLoaded}
+
+
+
+{:else if imageLoaded}
+
+

+
+{/if}
+
+
diff --git a/web/src/lib/components/memory-page/memory-video-viewer.svelte b/web/src/lib/components/memory-page/memory-video-viewer.svelte
new file mode 100644
index 0000000000..7758b067f3
--- /dev/null
+++ b/web/src/lib/components/memory-page/memory-video-viewer.svelte
@@ -0,0 +1,40 @@
+
+
+{#if showVideo}
+
+
+
+{/if}
diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte
index 77ccebe42b..f1a15f4429 100644
--- a/web/src/lib/components/memory-page/memory-viewer.svelte
+++ b/web/src/lib/components/memory-page/memory-viewer.svelte
@@ -4,6 +4,8 @@
import { intersectionObserver } from '$lib/actions/intersection-observer';
import { resizeObserver } from '$lib/actions/resize-observer';
import { shortcuts } from '$lib/actions/shortcut';
+ import MemoryPhotoViewer from '$lib/components/memory-page/memory-photo-viewer.svelte';
+ import MemoryVideoViewer from '$lib/components/memory-page/memory-video-viewer.svelte';
import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte';
import ArchiveAction from '$lib/components/photos-page/actions/archive-action.svelte';
import ChangeDate from '$lib/components/photos-page/actions/change-date-action.svelte';
@@ -23,7 +25,7 @@
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
- import { AppRoute, assetViewerFadeDuration, QueryParameter } from '$lib/constants';
+ import { AppRoute, QueryParameter } from '$lib/constants';
import { authManager } from '$lib/managers/auth-manager.svelte';
import type { TimelineAsset, Viewport } from '$lib/managers/timeline-manager/types';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -31,9 +33,8 @@
import { type MemoryAsset, memoryStore } from '$lib/stores/memory.store.svelte';
import { locale, videoViewerMuted, videoViewerVolume } from '$lib/stores/preferences.store';
import { preferences } from '$lib/stores/user.store';
- import { getAssetPlaybackUrl, getAssetThumbnailUrl, handlePromiseError, memoryLaneTitle } from '$lib/utils';
+ import { getAssetThumbnailUrl, handlePromiseError, memoryLaneTitle } from '$lib/utils';
import { cancelMultiselect } from '$lib/utils/asset-utils';
- import { getAltText } from '$lib/utils/thumbnail-util';
import { fromISODateTimeUTC, toTimelineAsset } from '$lib/utils/timeline-util';
import { AssetMediaSize, getAssetInfo } from '@immich/sdk';
import { IconButton } from '@immich/ui';
@@ -59,7 +60,6 @@
import { DateTime } from 'luxon';
import { t } from 'svelte-i18n';
import { Tween } from 'svelte/motion';
- import { fade } from 'svelte/transition';
let memoryGallery: HTMLElement | undefined = $state();
let memoryWrapper: HTMLElement | undefined = $state();
@@ -363,15 +363,16 @@
{/snippet}
-
handlePromiseError(handleAction('PlayPauseButtonClick', paused ? 'play' : 'pause'))}
- class="hover:text-black"
- />
+
+ handlePromiseError(handleAction('PlayPauseButtonClick', paused ? 'play' : 'pause'))}
+ />
+
{#each current.memory.assets as asset, index (asset.id)}
@@ -385,20 +386,23 @@
{(current.assetIndex + 1).toLocaleString($locale)}/{current.memory.assets.length.toLocaleString($locale)}
-
($videoViewerMuted = !$videoViewerMuted)}
- />
+
+
+ ($videoViewerMuted = !$videoViewerMuted)}
+ />
+
{#if galleryInView}