mirror of
https://github.com/immich-app/immich.git
synced 2025-08-11 09:16:31 -04:00
fix(web): prevent thumbhashes from covering search bar (#20720)
The thumbhash had a z-index setting which meant it would cover the search bar, and would always cause weird animations when scrolling up in search results. This is fixable by removing the z-index and moving it in front the other elements to get a naturally higher higher z-index preference.
This commit is contained in:
parent
f1c494ef97
commit
f36efd128b
@ -1,22 +0,0 @@
|
|||||||
import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
|
|
||||||
import { render } from '@testing-library/svelte';
|
|
||||||
|
|
||||||
describe('ImageThumbnail component', () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
Element.prototype.animate = vi.fn().mockImplementation(() => ({
|
|
||||||
cancel: () => {},
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows thumbhash while image is loading', () => {
|
|
||||||
const sut = render(ImageThumbnail, {
|
|
||||||
url: 'http://localhost/img.png',
|
|
||||||
altText: 'test',
|
|
||||||
base64ThumbHash: '1QcSHQRnh493V4dIh4eXh1h4kJUI',
|
|
||||||
widthStyle: '250px',
|
|
||||||
});
|
|
||||||
|
|
||||||
const thumbhash = sut.getByTestId('thumbhash');
|
|
||||||
expect(thumbhash).not.toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -45,4 +45,15 @@ describe('Thumbnail component', () => {
|
|||||||
const tabbables = getTabbable(container!);
|
const tabbables = getTabbable(container!);
|
||||||
expect(tabbables.length).toBe(0);
|
expect(tabbables.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows thumbhash while image is loading', () => {
|
||||||
|
const asset = assetFactory.build({ originalPath: 'image.jpg', originalMimeType: 'image/jpeg' });
|
||||||
|
const sut = render(Thumbnail, {
|
||||||
|
asset,
|
||||||
|
selected: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const thumbhash = sut.getByTestId('thumbhash');
|
||||||
|
expect(thumbhash).not.toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { thumbhash } from '$lib/actions/thumbhash';
|
|
||||||
import BrokenAsset from '$lib/components/assets/broken-asset.svelte';
|
import BrokenAsset from '$lib/components/assets/broken-asset.svelte';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { cancelImageUrl } from '$lib/utils/sw-messaging';
|
import { cancelImageUrl } from '$lib/utils/sw-messaging';
|
||||||
import { TUNABLES } from '$lib/utils/tunables';
|
|
||||||
import { mdiEyeOffOutline } from '@mdi/js';
|
import { mdiEyeOffOutline } from '@mdi/js';
|
||||||
import type { ActionReturn } from 'svelte/action';
|
import type { ActionReturn } from 'svelte/action';
|
||||||
import type { ClassValue } from 'svelte/elements';
|
import type { ClassValue } from 'svelte/elements';
|
||||||
import { fade } from 'svelte/transition';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
url: string;
|
url: string;
|
||||||
@ -15,7 +12,6 @@
|
|||||||
title?: string | null;
|
title?: string | null;
|
||||||
heightStyle?: string | undefined;
|
heightStyle?: string | undefined;
|
||||||
widthStyle: string;
|
widthStyle: string;
|
||||||
base64ThumbHash?: string | null;
|
|
||||||
curve?: boolean;
|
curve?: boolean;
|
||||||
shadow?: boolean;
|
shadow?: boolean;
|
||||||
circle?: boolean;
|
circle?: boolean;
|
||||||
@ -33,7 +29,6 @@
|
|||||||
title = null,
|
title = null,
|
||||||
heightStyle = undefined,
|
heightStyle = undefined,
|
||||||
widthStyle,
|
widthStyle,
|
||||||
base64ThumbHash = null,
|
|
||||||
curve = false,
|
curve = false,
|
||||||
shadow = false,
|
shadow = false,
|
||||||
circle = false,
|
circle = false,
|
||||||
@ -45,10 +40,6 @@
|
|||||||
brokenAssetClass = '',
|
brokenAssetClass = '',
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let {
|
|
||||||
IMAGE_THUMBNAIL: { THUMBHASH_FADE_DURATION },
|
|
||||||
} = TUNABLES;
|
|
||||||
|
|
||||||
let loaded = $state(false);
|
let loaded = $state(false);
|
||||||
let errored = $state(false);
|
let errored = $state(false);
|
||||||
|
|
||||||
@ -100,7 +91,6 @@
|
|||||||
alt={loaded || errored ? altText : ''}
|
alt={loaded || errored ? altText : ''}
|
||||||
{title}
|
{title}
|
||||||
class={['object-cover', optionalClasses, imageClass]}
|
class={['object-cover', optionalClasses, imageClass]}
|
||||||
class:opacity-0={!thumbhash && !loaded}
|
|
||||||
draggable="false"
|
draggable="false"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@ -110,19 +100,3 @@
|
|||||||
<Icon {title} path={mdiEyeOffOutline} size="2em" class={hiddenIconClass} />
|
<Icon {title} path={mdiEyeOffOutline} size="2em" class={hiddenIconClass} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if base64ThumbHash && (!loaded || errored)}
|
|
||||||
<canvas
|
|
||||||
use:thumbhash={{ base64ThumbHash }}
|
|
||||||
data-testid="thumbhash"
|
|
||||||
style:width={widthStyle}
|
|
||||||
style:height={heightStyle}
|
|
||||||
{title}
|
|
||||||
class="absolute top-0 object-cover"
|
|
||||||
class:rounded-xl={curve}
|
|
||||||
class:shadow-lg={shadow}
|
|
||||||
class:rounded-full={circle}
|
|
||||||
draggable="false"
|
|
||||||
out:fade={{ duration: THUMBHASH_FADE_DURATION }}
|
|
||||||
></canvas>
|
|
||||||
{/if}
|
|
||||||
|
@ -230,15 +230,6 @@
|
|||||||
]}
|
]}
|
||||||
data-outline
|
data-outline
|
||||||
></div>
|
></div>
|
||||||
{#if (!loaded || thumbError) && asset.thumbhash}
|
|
||||||
<canvas
|
|
||||||
use:thumbhash={{ base64ThumbHash: asset.thumbhash }}
|
|
||||||
class="absolute object-cover z-1"
|
|
||||||
style:width="{width}px"
|
|
||||||
style:height="{height}px"
|
|
||||||
out:fade={{ duration: THUMBHASH_FADE_DURATION }}
|
|
||||||
></canvas>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={['group absolute -top-[0px] -bottom-[0px]', { 'cursor-not-allowed': disabled, 'cursor-pointer': !disabled }]}
|
class={['group absolute -top-[0px] -bottom-[0px]', { 'cursor-not-allowed': disabled, 'cursor-pointer': !disabled }]}
|
||||||
@ -352,7 +343,21 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if (!loaded || thumbError) && asset.thumbhash}
|
||||||
|
<canvas
|
||||||
|
use:thumbhash={{ base64ThumbHash: asset.thumbhash }}
|
||||||
|
data-testid="thumbhash"
|
||||||
|
class="absolute top-0 object-cover"
|
||||||
|
style:width="{width}px"
|
||||||
|
style:height="{height}px"
|
||||||
|
class:rounded-xl={selected}
|
||||||
|
draggable="false"
|
||||||
|
out:fade={{ duration: THUMBHASH_FADE_DURATION }}
|
||||||
|
></canvas>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if selectionCandidate}
|
{#if selectionCandidate}
|
||||||
<div
|
<div
|
||||||
class="absolute top-0 h-full w-full bg-immich-primary opacity-40"
|
class="absolute top-0 h-full w-full bg-immich-primary opacity-40"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user