Extract HMR logic into reusable component
• Create dedicated Hmr component for hot module replacement handling • Remove inline HMR code from base-timeline-viewer • Simplify timeline viewer by delegating HMR concerns to specialized component
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
import { afterNavigate, beforeNavigate } from '$app/navigation';
|
import { afterNavigate, beforeNavigate } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer';
|
import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer';
|
||||||
|
import Hmr from '$lib/components/timeline/base-components/hmr.svelte';
|
||||||
import Skeleton from '$lib/components/timeline/base-components/skeleton.svelte';
|
import Skeleton from '$lib/components/timeline/base-components/skeleton.svelte';
|
||||||
import SelectableTimelineDay from '$lib/components/timeline/internal-components/selectable-timeline-day.svelte';
|
import SelectableTimelineDay from '$lib/components/timeline/internal-components/selectable-timeline-day.svelte';
|
||||||
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
|
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
|
||||||
@@ -11,9 +12,7 @@
|
|||||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||||
import { navigate } from '$lib/utils/navigation';
|
|
||||||
import { onMount, type Snippet } from 'svelte';
|
import { onMount, type Snippet } from 'svelte';
|
||||||
import type { UpdatePayload } from 'vite';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
customThumbnailLayout?: Snippet<[TimelineAsset]>;
|
customThumbnailLayout?: Snippet<[TimelineAsset]>;
|
||||||
@@ -171,47 +170,6 @@
|
|||||||
complete.then(completeNav, completeNav);
|
complete.then(completeNav, completeNav);
|
||||||
});
|
});
|
||||||
|
|
||||||
const hmrSupport = () => {
|
|
||||||
// when hmr happens, skeleton is initialized to true by default
|
|
||||||
// normally, loading asset-grid is part of a navigation event, and the completion of
|
|
||||||
// that event triggers a scroll-to-asset, if necessary, when then clears the skeleton.
|
|
||||||
// this handler will run the navigation/scroll-to-asset handler when hmr is performed,
|
|
||||||
// preventing skeleton from showing after hmr
|
|
||||||
if (import.meta && import.meta.hot) {
|
|
||||||
const afterApdate = (payload: UpdatePayload) => {
|
|
||||||
const assetGridUpdate = payload.updates.some(
|
|
||||||
(update) => update.path.endsWith('asset-grid.svelte') || update.path.endsWith('assets-store.ts'),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (assetGridUpdate) {
|
|
||||||
setTimeout(() => {
|
|
||||||
const asset = $page.url.searchParams.get('at');
|
|
||||||
if (asset) {
|
|
||||||
$gridScrollTarget = { at: asset };
|
|
||||||
void navigate(
|
|
||||||
{ targetRoute: 'current', assetId: null, assetGridRouteSearchParams: $gridScrollTarget },
|
|
||||||
{ replaceState: true, forceNavigate: true },
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
scrollToTop();
|
|
||||||
}
|
|
||||||
showSkeleton = false;
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
import.meta.hot?.on('vite:afterUpdate', afterApdate);
|
|
||||||
import.meta.hot?.on('vite:beforeUpdate', (payload) => {
|
|
||||||
const assetGridUpdate = payload.updates.some((update) => update.path.endsWith('asset-grid.svelte'));
|
|
||||||
if (assetGridUpdate) {
|
|
||||||
timelineManager.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => import.meta.hot?.off('vite:afterUpdate', afterApdate);
|
|
||||||
}
|
|
||||||
return () => void 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateIsScrolling = () => (timelineManager.scrolling = true);
|
const updateIsScrolling = () => (timelineManager.scrolling = true);
|
||||||
// note: don't throttle, debounce, or otherwise do this function async - it causes flicker
|
// note: don't throttle, debounce, or otherwise do this function async - it causes flicker
|
||||||
const updateSlidingWindow = () => timelineManager.updateSlidingWindow(element?.scrollTop || 0);
|
const updateSlidingWindow = () => timelineManager.updateSlidingWindow(element?.scrollTop || 0);
|
||||||
@@ -236,13 +194,19 @@
|
|||||||
if (!enableRouting) {
|
if (!enableRouting) {
|
||||||
showSkeleton = false;
|
showSkeleton = false;
|
||||||
}
|
}
|
||||||
const disposeHmr = hmrSupport();
|
|
||||||
return () => {
|
|
||||||
disposeHmr();
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Hmr
|
||||||
|
onHmr={() => {
|
||||||
|
const asset = $page.url.searchParams.get('at');
|
||||||
|
if (asset) {
|
||||||
|
$gridScrollTarget = { at: asset };
|
||||||
|
}
|
||||||
|
void completeNav();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{@render header?.(scrollTop)}
|
{@render header?.(scrollTop)}
|
||||||
|
|
||||||
<!-- Right margin MUST be equal to the width of scrubber -->
|
<!-- Right margin MUST be equal to the width of scrubber -->
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import type { UpdatePayload } from 'vite';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onHmr: () => void;
|
||||||
|
}
|
||||||
|
let { onHmr }: Props = $props();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const hmrSupport = () => {
|
||||||
|
// when hmr happens, skeleton is initialized to true by default
|
||||||
|
// normally, loading asset-grid is part of a navigation event, and the completion of
|
||||||
|
// that event triggers a scroll-to-asset, if necessary, when then clears the skeleton.
|
||||||
|
// this handler will run the navigation/scroll-to-asset handler when hmr is performed,
|
||||||
|
// preventing skeleton from showing after hmr
|
||||||
|
if (import.meta && import.meta?.hot) {
|
||||||
|
const afterUpdate = (payload: UpdatePayload) => {
|
||||||
|
const assetGridUpdate = payload.updates.some((update) => update.path.endsWith('base-timeline-viewer.svelte'));
|
||||||
|
if (assetGridUpdate) {
|
||||||
|
setTimeout(onHmr, 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
import.meta.hot?.on('vite:afterUpdate', afterUpdate);
|
||||||
|
return () => import.meta.hot?.off('vite:afterUpdate', afterUpdate);
|
||||||
|
}
|
||||||
|
return () => void 0;
|
||||||
|
};
|
||||||
|
return hmrSupport();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user