Selaa lähdekoodia

fix(web): profile image load (#2434)

Michel Heusschen 2 vuotta sitten
vanhempi
commit
15fa8250cb

+ 3 - 2
web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte

@@ -2,6 +2,7 @@
 	import { goto } from '$app/navigation';
 	import { page } from '$app/stores';
 	import { clickOutside } from '$lib/utils/click-outside';
+	import { imageLoad } from '$lib/utils/image-load';
 	import { createEventDispatcher } from 'svelte';
 	import { fade, fly } from 'svelte/transition';
 	import TrayArrowUp from 'svelte-material-icons/TrayArrowUp.svelte';
@@ -124,13 +125,13 @@
 					>
 						{#if user.profileImagePath}
 							<img
-								transition:fade={{ duration: 100 }}
 								class:hidden={showProfilePictureFallback}
 								src={`${$page.url.origin}/api/user/profile-image/${user.id}`}
 								alt="profile-img"
 								class="inline rounded-full h-12 w-12 object-cover shadow-md border-2 border-immich-primary hover:border-immich-dark-primary dark:hover:border-immich-primary dark:border-immich-dark-primary transition-all"
 								draggable="false"
-								on:load={() => (showProfilePictureFallback = false)}
+								use:imageLoad
+								on:image-load={() => (showProfilePictureFallback = false)}
 							/>
 						{/if}
 						{#if showProfilePictureFallback}

+ 38 - 0
web/src/lib/utils/image-load.ts

@@ -0,0 +1,38 @@
+import { tick } from 'svelte';
+import type { ActionReturn } from 'svelte/action';
+
+interface Attributes {
+	'on:image-error'?: (e: CustomEvent) => void;
+	'on:image-load'?: (e: CustomEvent) => void;
+}
+
+export function imageLoad(img: HTMLImageElement): ActionReturn<void, Attributes> {
+	const onImageError = () => img.dispatchEvent(new CustomEvent('image-error'));
+	const onImageLoaded = () => img.dispatchEvent(new CustomEvent('image-load'));
+
+	if (img.complete) {
+		// Browser has fetched the image, naturalHeight is used to check
+		// if any loading errors have occurred.
+		const loadingError = img.naturalHeight === 0;
+
+		// Report status after a tick, to make sure event listeners are registered.
+		if (loadingError) {
+			tick().then(onImageError);
+		} else {
+			tick().then(onImageLoaded);
+		}
+
+		return {};
+	}
+
+	// Image has not been loaded yet, report status with event listeners.
+	img.addEventListener('load', onImageLoaded, { once: true });
+	img.addEventListener('error', onImageError, { once: true });
+
+	return {
+		destroy() {
+			img.removeEventListener('load', onImageLoaded);
+			img.removeEventListener('error', onImageError);
+		}
+	};
+}