refactor scrollCompensation a bit more

This commit is contained in:
midzelis 2025-08-24 18:13:16 +00:00
parent 2a55b05a25
commit 88ca63ff47
3 changed files with 21 additions and 19 deletions

View File

@ -96,14 +96,26 @@
updateSlidingWindow(); updateSlidingWindow();
}; };
const scrollCompensation = (compensation: { heightDelta?: number; scrollTop?: number }) => {
const { heightDelta, scrollTop } = compensation;
if (heightDelta !== undefined) {
scrollBy(heightDelta);
} else if (scrollTop !== undefined) {
scrollTo(scrollTop);
}
timelineManager.clearScrollCompensation();
};
const getAssetHeight = (assetId: string, monthGroup: MonthGroup) => { const getAssetHeight = (assetId: string, monthGroup: MonthGroup) => {
// the following method may trigger any layouts, so need to // the following method may trigger any layouts, so need to
// handle any scroll compensation that may have been set // handle any scroll compensation that may have been set
const height = monthGroup!.findAssetAbsolutePosition(assetId); const height = monthGroup!.findAssetAbsolutePosition(assetId);
// this is in a while loop, since scrollCompensations invoke scrolls
// which may load months, triggering more scrollCompensations. Call
// this in a loop, until no more layouts occur.
while (timelineManager.scrollCompensation.monthGroup) { while (timelineManager.scrollCompensation.monthGroup) {
scrollCompensation(timelineManager.scrollCompensation); scrollCompensation(timelineManager.scrollCompensation);
timelineManager.clearScrollCompensation();
} }
return height; return height;
}; };
@ -171,15 +183,6 @@
// Also note: don't throttle, debounce, or otherwise do this function async - it causes flicker // Also 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);
const scrollCompensation = ({ heightDelta, scrollTop }: { heightDelta?: number; scrollTop?: number }) => {
if (heightDelta !== undefined) {
scrollBy(heightDelta);
} else if (scrollTop !== undefined) {
scrollTo(scrollTop);
}
};
const onScrollCompensation = scrollCompensation;
const topSectionResizeObserver: OnResizeCallback = ({ height }) => (timelineManager.topSectionHeight = height); const topSectionResizeObserver: OnResizeCallback = ({ height }) => (timelineManager.topSectionHeight = height);
onMount(() => { onMount(() => {
@ -284,7 +287,7 @@
} }
onSelect?.(asset); onSelect?.(asset);
}} }}
{onScrollCompensation} onScrollCompensationMonthInDOM={scrollCompensation}
/> />
</div> </div>
{/if} {/if}

View File

@ -25,14 +25,14 @@
monthGroup: MonthGroup; monthGroup: MonthGroup;
timelineManager: TimelineManager; timelineManager: TimelineManager;
onScrollCompensation: (compensation: { heightDelta?: number; scrollTop?: number }) => void; onScrollCompensationMonthInDOM: (compensation: { heightDelta?: number; scrollTop?: number }) => void;
onHover: (dayGroup: DayGroup, asset: TimelineAsset) => void; onHover: (dayGroup: DayGroup, asset: TimelineAsset) => void;
onAssetOpen: (dayGroup: DayGroup, asset: TimelineAsset) => void; onAssetOpen: (dayGroup: DayGroup, asset: TimelineAsset) => void;
onAssetSelect: (dayGroup: DayGroup, asset: TimelineAsset) => void; onAssetSelect: (dayGroup: DayGroup, asset: TimelineAsset) => void;
onDayGroupSelect: (dayGroup: DayGroup, assets: TimelineAsset[]) => void; onDayGroupSelect: (dayGroup: DayGroup, assets: TimelineAsset[]) => void;
// these should be replaced with reactive properties in timelinemanager // these should be replaced with reactive properties in timeline-manager.svelte.ts
isDayGroupSelected: (dayGroup: DayGroup) => boolean; isDayGroupSelected: (dayGroup: DayGroup) => boolean;
isAssetSelected: (asset: TimelineAsset) => boolean; isAssetSelected: (asset: TimelineAsset) => boolean;
isAssetSelectionCandidate: (asset: TimelineAsset) => boolean; isAssetSelectionCandidate: (asset: TimelineAsset) => boolean;
@ -47,7 +47,7 @@
showArchiveIcon, showArchiveIcon,
monthGroup, monthGroup,
timelineManager, timelineManager,
onScrollCompensation, onScrollCompensationMonthInDOM,
onHover, onHover,
onAssetOpen, onAssetOpen,
@ -74,8 +74,7 @@
$effect.root(() => { $effect.root(() => {
if (timelineManager.scrollCompensation.monthGroup === monthGroup) { if (timelineManager.scrollCompensation.monthGroup === monthGroup) {
onScrollCompensation(timelineManager.scrollCompensation); onScrollCompensationMonthInDOM(timelineManager.scrollCompensation);
timelineManager.clearScrollCompensation();
} }
}); });
</script> </script>

View File

@ -25,7 +25,7 @@
onAssetOpen?: (dayGroup: DayGroup, asset: TimelineAsset, defaultAssetOpen: () => void) => void; onAssetOpen?: (dayGroup: DayGroup, asset: TimelineAsset, defaultAssetOpen: () => void) => void;
onSelect?: (isSingleSelect: boolean, asset: TimelineAsset) => void; onSelect?: (isSingleSelect: boolean, asset: TimelineAsset) => void;
onScrollCompensation: (compensation: { heightDelta?: number; scrollTop?: number }) => void; onScrollCompensationMonthInDOM: (compensation: { heightDelta?: number; scrollTop?: number }) => void;
} }
let { let {
@ -39,7 +39,7 @@
timelineManager, timelineManager,
onAssetOpen, onAssetOpen,
onSelect, onSelect,
onScrollCompensation, onScrollCompensationMonthInDOM,
}: Props = $props(); }: Props = $props();
let lastAssetMouseEvent: TimelineAsset | null = $state(null); let lastAssetMouseEvent: TimelineAsset | null = $state(null);
@ -264,7 +264,7 @@
{showArchiveIcon} {showArchiveIcon}
{monthGroup} {monthGroup}
{timelineManager} {timelineManager}
{onScrollCompensation} {onScrollCompensationMonthInDOM}
onHover={handleOnHover} onHover={handleOnHover}
onAssetOpen={handleOnAssetOpen} onAssetOpen={handleOnAssetOpen}
onAssetSelect={handleAssetSelect} onAssetSelect={handleAssetSelect}