refactor(web): convert timeline layout options to derived state

- Replace createLayoutOptions() method with derived layoutOptions property for better reactivity. 
- Remove duplicate refreshLayout() implementation 
- Simplify setLayoutOptions() by removing unnecessary change tracking.
This commit is contained in:
midzelis 2025-09-28 01:45:23 +00:00
parent 674def4088
commit 575eecfd97
4 changed files with 13 additions and 28 deletions

View file

@ -230,7 +230,7 @@
<div
class="month-group"
style:margin-bottom={timelineManager.createLayoutOptions().spacing + 'px'}
style:margin-bottom={timelineManager.layoutOptions.spacing + 'px'}
style:position="absolute"
style:transform={`translate3d(0,${absoluteHeight}px,0)`}
style:height={`${monthGroup.height}px`}

View file

@ -35,6 +35,13 @@ export abstract class PhotostreamManager {
bottom: this.#scrollTop + this.viewportHeight,
}));
layoutOptions = $derived({
spacing: 2,
heightTolerance: 0.15,
rowHeight: this.rowHeight,
rowWidth: Math.floor(this.viewportWidth),
});
protected initTask = new CancellableTask(
() => (this.isInitialized = true),
() => (this.isInitialized = false),
@ -58,13 +65,9 @@ export abstract class PhotostreamManager {
abstract get months(): PhotostreamSegment[];
setLayoutOptions({ headerHeight = 48, rowHeight = 235, gap = 12 }: TimelineManagerLayoutOptions) {
let changed = false;
changed ||= this.#setHeaderHeight(headerHeight);
changed ||= this.#setGap(gap);
changed ||= this.#setRowHeight(rowHeight);
if (changed) {
this.refreshLayout();
}
this.#setHeaderHeight(headerHeight);
this.#setGap(gap);
this.#setRowHeight(rowHeight);
}
#setHeaderHeight(value: number) {
@ -208,17 +211,6 @@ export abstract class PhotostreamManager {
this.updateIntersections();
}
createLayoutOptions() {
const viewportWidth = this.viewportWidth;
return {
spacing: 2,
heightTolerance: 0.15,
rowHeight: this.#rowHeight,
rowWidth: Math.floor(viewportWidth),
};
}
async loadSegment(identifier: SegmentIdentifier, options?: { cancelable: boolean }): Promise<void> {
let cancelable = true;
if (options) {
@ -253,13 +245,6 @@ export abstract class PhotostreamManager {
return Promise.resolve(void 0);
}
refreshLayout() {
for (const month of this.months) {
updateGeometry(this, month, { invalidateHeight: true });
}
this.updateIntersections();
}
getMaxScrollPercent() {
const totalHeight = this.timelineHeight + this.bottomSectionHeight + this.topSectionHeight;
return (totalHeight - this.viewportHeight) / totalHeight;

View file

@ -75,7 +75,7 @@ export class SearchResultsSegment extends PhotostreamSegment {
layout(): void {
const timelineAssets = this.#viewerAssets.map((viewerAsset) => viewerAsset.asset);
const layoutOptions = this.timelineManager.createLayoutOptions();
const layoutOptions = this.timelineManager.layoutOptions;
const geometry = getJustifiedLayoutFromAssets(timelineAssets, layoutOptions);
this.height = timelineAssets.length === 0 ? 0 : geometry.containerHeight + this.timelineManager.headerHeight;

View file

@ -34,7 +34,7 @@ export function layoutMonthGroup(timelineManager: TimelineManager, month: MonthG
let dayGroupRow = 0;
let dayGroupCol = 0;
const options = timelineManager.createLayoutOptions();
const options = timelineManager.layoutOptions;
for (const dayGroup of month.dayGroups) {
dayGroup.layout(options, noDefer);