Skip to content

Commit

Permalink
fix(web): use native image decoder
Browse files Browse the repository at this point in the history
The decode function should be more reliable than event listeners and doesn't
need additional logic for destruction. The semantics of decode are also
different to the 'load' event listener. 'decode' will wait until the image
has been fully decoded and can be rendered, unlike 'load' which will trigger
before the image has actually been decoded.

Fixes: #3073
  • Loading branch information
uhthomas committed Jul 2, 2023
1 parent d9e0847 commit 485b326
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<section class="flex flex-wrap gap-14 px-20 overflow-y-auto">
<!-- Image grid -->
<div class="flex flex-wrap gap-[2px]">
{#each album.assets as asset}
{#each album.assets as asset (asset.id)}
<Thumbnail {asset} on:click={() => (selectedThumbnail = asset)} selected={isSelected(asset.id)} />
{/each}
</div>
Expand Down
14 changes: 10 additions & 4 deletions web/src/lib/components/assets/thumbnail/image-thumbnail.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script lang="ts">
import { imageLoad } from '$lib/utils/image-load';
import { Buffer } from 'buffer';
import { onMount, tick } from 'svelte';
import { fade } from 'svelte/transition';
import { thumbHashToDataURL } from 'thumbhash';
import { Buffer } from 'buffer';
export let url: string;
export let altText: string;
Expand All @@ -13,10 +13,18 @@
export let shadow = false;
export let circle = false;
let img: HTMLImageElement;
let complete = false;
onMount(async () => {
await img.decode();
await tick();
complete = true;
});
</script>

<img
bind:this={img}
style:width={widthStyle}
style:height={heightStyle}
src={url}
Expand All @@ -27,8 +35,6 @@
class:rounded-full={circle}
class:opacity-0={!thumbhash && !complete}
draggable="false"
use:imageLoad
on:image-load|once={() => (complete = true)}
/>

{#if thumbhash && !complete}
Expand Down
17 changes: 14 additions & 3 deletions web/src/lib/components/shared-components/user-avatar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
</script>

<script lang="ts">
import { imageLoad } from '$lib/utils/image-load';
import { api, UserResponseDto } from '@api';
import { onMount, tick } from 'svelte';
export let user: UserResponseDto;
export let color: Color = 'primary';
Expand All @@ -14,8 +14,20 @@
export let interactive = false;
export let showTitle = true;
export let autoColor = false;
let img: HTMLImageElement;
let showFallback = true;
onMount(async () => {
if (!user.profileImagePath) {
return;
}
await img.decode();
await tick();
showFallback = false;
});
const colorClasses: Record<Color, string> = {
primary: 'bg-immich-primary dark:bg-immich-dark-primary text-immich-dark-fg dark:text-immich-fg',
pink: 'bg-pink-400 text-immich-bg',
Expand Down Expand Up @@ -55,13 +67,12 @@
>
{#if user.profileImagePath}
<img
bind:this={img}
src={api.getProfileImageUrl(user.id)}
alt="Profile image of {title}"
class="object-cover w-full h-full"
class:hidden={showFallback}
draggable="false"
use:imageLoad
on:image-load={() => (showFallback = false)}
/>
{/if}
{#if showFallback}
Expand Down
38 changes: 0 additions & 38 deletions web/src/lib/utils/image-load.ts

This file was deleted.

4 changes: 2 additions & 2 deletions web/src/routes/(user)/explore/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
import { AppRoute } from '$lib/constants';
import { AssetTypeEnum, SearchExploreResponseDto, api } from '@api';
import { api, AssetTypeEnum, SearchExploreResponseDto } from '@api';
import ClockOutline from 'svelte-material-icons/ClockOutline.svelte';
import HeartMultipleOutline from 'svelte-material-icons/HeartMultipleOutline.svelte';
import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte';
Expand Down Expand Up @@ -66,7 +66,7 @@
<p class="mb-4 dark:text-immich-dark-fg font-medium">Places</p>
</div>
<div class="flex flex-row flex-wrap gap-4">
{#each places as item}
{#each places as item (item.data.id)}
<a class="relative" href="/search?{Field.CITY}={item.value}" draggable="false">
<div
class="filter brightness-75 rounded-xl overflow-hidden w-[calc((100vw-(72px+5rem))/2)] max-w-[156px] flex justify-center"
Expand Down

0 comments on commit 485b326

Please sign in to comment.