test: fix scroll flicker 2

pull/28654/head
Alex Tran 2026-05-27 15:43:25 -05:00
parent a5ce3fc927
commit 0b15a90618
3 changed files with 29 additions and 20 deletions

View File

@ -67,3 +67,11 @@ export function calculateViewerAssetViewportProximity(
timelineManager.visibleWindow.bottom + headerHeight, timelineManager.visibleWindow.bottom + headerHeight,
); );
} }
export function calculateViewerAssetIsInOrNearViewport(
timelineManager: TimelineManager,
positionTop: number,
positionHeight: number,
) {
return isInOrNearViewport(calculateViewerAssetViewportProximity(timelineManager, positionTop, positionHeight));
}

View File

@ -29,7 +29,8 @@ import type { AssetDescriptor, Direction, MoveAsset, TimelineAsset } from './typ
import { ViewerAsset } from './viewer-asset.svelte'; import { ViewerAsset } from './viewer-asset.svelte';
export class TimelineMonth { export class TimelineMonth {
#viewportProximity: ViewportProximity = $state(ViewportProximity.FarFromViewport); #isInOrNearViewport = $state(false);
#isInViewport = $state(false);
isLoaded: boolean = $state(false); isLoaded: boolean = $state(false);
timelineDays: TimelineDay[] = $state([]); timelineDays: TimelineDay[] = $state([]);
readonly timelineManager: TimelineManager; readonly timelineManager: TimelineManager;
@ -85,24 +86,28 @@ export class TimelineMonth {
} }
set viewportProximity(newValue: ViewportProximity) { set viewportProximity(newValue: ViewportProximity) {
const old = this.#viewportProximity; const isInOrNearViewport = isInOrNearViewportUtil(newValue);
if (old === newValue) { if (this.#isInOrNearViewport !== isInOrNearViewport) {
return; this.#isInOrNearViewport = isInOrNearViewport;
if (isInOrNearViewport) {
void this.timelineManager.loadTimelineMonth(this.yearMonth);
} else {
this.cancel();
}
} }
this.#viewportProximity = newValue;
if (isInOrNearViewportUtil(newValue)) { const isInViewport = isInViewportUtil(newValue);
void this.timelineManager.loadTimelineMonth(this.yearMonth); if (this.#isInViewport !== isInViewport) {
} else { this.#isInViewport = isInViewport;
this.cancel();
} }
} }
get isInOrNearViewport() { get isInOrNearViewport() {
return isInOrNearViewportUtil(this.#viewportProximity); return this.#isInOrNearViewport;
} }
get isInViewport() { get isInViewport() {
return isInViewportUtil(this.#viewportProximity); return this.#isInViewport;
} }
get lastTimelineDay() { get lastTimelineDay() {

View File

@ -1,28 +1,24 @@
import type { CommonPosition } from '$lib/utils/layout-utils'; import type { CommonPosition } from '$lib/utils/layout-utils';
import { import { calculateViewerAssetIsInOrNearViewport } from './internal/intersection-support.svelte';
ViewportProximity,
calculateViewerAssetViewportProximity,
isInOrNearViewport,
} from './internal/intersection-support.svelte';
import type { TimelineDay } from './timeline-day.svelte'; import type { TimelineDay } from './timeline-day.svelte';
import type { TimelineAsset } from './types'; import type { TimelineAsset } from './types';
export class ViewerAsset { export class ViewerAsset {
readonly #group: TimelineDay; readonly #group: TimelineDay;
#viewportProximity = $derived.by(() => { #isInOrNearViewport = $derived.by(() => {
if (!this.position) { if (!this.position) {
return ViewportProximity.FarFromViewport; return false;
} }
const store = this.#group.timelineMonth.timelineManager; const store = this.#group.timelineMonth.timelineManager;
const positionTop = this.#group.absoluteTimelineDayTop + this.position.top; const positionTop = this.#group.absoluteTimelineDayTop + this.position.top;
return calculateViewerAssetViewportProximity(store, positionTop, this.position.height); return calculateViewerAssetIsInOrNearViewport(store, positionTop, this.position.height);
}); });
get isInOrNearViewport() { get isInOrNearViewport() {
return isInOrNearViewport(this.#viewportProximity); return this.#isInOrNearViewport;
} }
position: CommonPosition | undefined = $state.raw(); position: CommonPosition | undefined = $state.raw();