Compare commits

...

1 Commits

Author SHA1 Message Date
Michel Heusschen b93632ddcb fix(web): prevent timeline DOM retention during scroll 2026-05-01 15:35:56 +02:00
3 changed files with 9 additions and 21 deletions
@@ -2,20 +2,16 @@
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { filterIsInOrNearViewport } from '$lib/managers/timeline-manager/utils.svelte';
import type { ViewerAsset } from '$lib/managers/timeline-manager/viewer-asset.svelte';
import type { VirtualScrollManager } from '$lib/managers/VirtualScrollManager/VirtualScrollManager.svelte';
import { uploadAssetsStore } from '$lib/stores/upload';
import type { CommonPosition } from '$lib/utils/layout-utils';
import type { Snippet } from 'svelte';
import { flip } from 'svelte/animate';
import { scale } from 'svelte/transition';
let { isUploading } = uploadAssetsStore;
type Props = {
viewerAssets: ViewerAsset[];
width: number;
height: number;
manager: VirtualScrollManager;
suspendTransitions: boolean;
thumbnail: Snippet<
[
{
@@ -27,10 +23,7 @@
customThumbnailLayout?: Snippet<[asset: TimelineAsset]>;
};
const { viewerAssets, width, height, manager, thumbnail, customThumbnailLayout }: Props = $props();
const transitionDuration = $derived(manager.suspendTransitions && !$isUploading ? 0 : 150);
const scaleDuration = $derived(transitionDuration === 0 ? 0 : transitionDuration + 100);
const { viewerAssets, width, height, suspendTransitions, thumbnail, customThumbnailLayout }: Props = $props();
</script>
<!-- Image grid -->
@@ -40,6 +33,7 @@
{@const asset = viewerAsset.asset!}
<!-- note: don't remove data-asset-id - its used by web e2e tests -->
<!-- Be careful with $derived values in out:scale, because Svelte can retain DOM nodes -->
<div
data-asset-id={asset.id}
class="absolute"
@@ -47,8 +41,8 @@
style:inset-inline-start={position.left + 'px'}
style:width={position.width + 'px'}
style:height={position.height + 'px'}
out:scale|global={{ start: 0.1, duration: scaleDuration }}
animate:flip={{ duration: transitionDuration }}
out:scale|global={{ start: 0.1, duration: suspendTransitions ? 0 : 250 }}
animate:flip={{ duration: suspendTransitions ? 0 : 150 }}
>
{@render thumbnail({ asset, position })}
{@render customThumbnailLayout?.(asset)}
+4 -9
View File
@@ -5,7 +5,6 @@
import type { TimelineMonth } from '$lib/managers/timeline-manager/timeline-month.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { assetsSnapshot, filterIsInOrNearViewport } from '$lib/managers/timeline-manager/utils.svelte';
import type { VirtualScrollManager } from '$lib/managers/VirtualScrollManager/VirtualScrollManager.svelte';
import { uploadAssetsStore } from '$lib/stores/upload';
import type { CommonPosition } from '$lib/utils/layout-utils';
import { fromTimelinePlainDate, getDateLocaleString } from '$lib/utils/timeline-util';
@@ -28,7 +27,6 @@
singleSelect: boolean;
assetInteraction: AssetMultiSelectManager;
timelineMonth: TimelineMonth;
manager: VirtualScrollManager;
onTimelineDaySelect: (timelineDay: TimelineDay, assets: TimelineAsset[]) => void;
};
let {
@@ -37,14 +35,13 @@
singleSelect,
assetInteraction,
timelineMonth,
manager,
onTimelineDaySelect,
}: Props = $props();
let { isUploading } = uploadAssetsStore;
let hoveredTimelineDay = $state<string | null>(null);
const transitionDuration = $derived(timelineMonth.timelineManager.suspendTransitions && !$isUploading ? 0 : 150);
const suspendTransitions = $derived(timelineMonth.timelineManager.suspendTransitions && !$isUploading);
const getTimelineDayFullDate = (timelineDay: TimelineDay): string => {
const { month, year } = timelineDay.timelineMonth.yearMonth;
@@ -61,10 +58,8 @@
{@const isTimelineDaySelected = assetInteraction.selectedGroup.has(timelineDay.groupTitle)}
<!-- svelte-ignore a11y_no_static_element_interactions -->
<section
class={[
{ 'transition-all': !timelineMonth.timelineManager.suspendTransitions },
!timelineMonth.timelineManager.suspendTransitions && `delay-${transitionDuration}`,
]}
class:transition-all={!suspendTransitions}
class:delay-150={!suspendTransitions}
data-group
style:position="absolute"
style:inset-inline-start={timelineDay.start + 'px'}
@@ -99,10 +94,10 @@
</div>
<AssetLayout
{manager}
viewerAssets={timelineDay.viewerAssets}
height={timelineDay.height}
width={timelineDay.width}
{suspendTransitions}
{customThumbnailLayout}
>
{#snippet thumbnail({ asset, position })}
@@ -670,7 +670,6 @@
{customThumbnailLayout}
{singleSelect}
{timelineMonth}
manager={timelineManager}
onTimelineDaySelect={handleGroupSelect}
>
{#snippet thumbnail({ asset, position, timelineDay, groupIndex })}