mirror of
https://github.com/immich-app/immich.git
synced 2025-01-28 00:59:18 -05:00
fix(web): better year labels (#5009)
* better year labels * fixes * lint fixes
This commit is contained in:
parent
c3f8dc8c22
commit
0c482960ce
1 changed files with 34 additions and 42 deletions
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { AssetStore } from '$lib/stores/assets.store';
|
import type { AssetStore, AssetBucket } from '$lib/stores/assets.store';
|
||||||
|
import type { DateTime } from 'luxon';
|
||||||
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
@ -18,30 +19,41 @@
|
||||||
const toTimelineY = (scrollY: number) => Math.round((scrollY * $assetStore.timelineHeight) / height);
|
const toTimelineY = (scrollY: number) => Math.round((scrollY * $assetStore.timelineHeight) / height);
|
||||||
|
|
||||||
const HOVER_DATE_HEIGHT = 30;
|
const HOVER_DATE_HEIGHT = 30;
|
||||||
|
const MIN_YEAR_LABEL_DISTANCE = 16;
|
||||||
|
|
||||||
$: hoverY = height - windowHeight + clientY;
|
$: hoverY = height - windowHeight + clientY;
|
||||||
$: scrollY = toScrollY(timelineY);
|
$: scrollY = toScrollY(timelineY);
|
||||||
|
|
||||||
class Segment {
|
class Segment {
|
||||||
public count;
|
public count = 0;
|
||||||
public height;
|
public height = 0;
|
||||||
public timeGroup;
|
public timeGroup = '';
|
||||||
|
public date!: DateTime;
|
||||||
constructor({ count = 0, height = 0, timeGroup = '' }) {
|
public hasLabel = false;
|
||||||
this.count = count;
|
|
||||||
this.height = height;
|
|
||||||
this.timeGroup = timeGroup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$: segments = $assetStore.buckets.map(
|
const calculateSegments = (buckets: AssetBucket[]) => {
|
||||||
(bucket) =>
|
let height = 0;
|
||||||
new Segment({
|
let prev: Segment;
|
||||||
count: bucket.assets.length,
|
return buckets.map((bucket) => {
|
||||||
height: toScrollY(bucket.bucketHeight),
|
const segment = new Segment();
|
||||||
timeGroup: bucket.bucketDate,
|
segment.count = bucket.assets.length;
|
||||||
}),
|
segment.height = toScrollY(bucket.bucketHeight);
|
||||||
);
|
segment.timeGroup = bucket.bucketDate;
|
||||||
|
segment.date = fromLocalDateTime(segment.timeGroup);
|
||||||
|
|
||||||
|
if (prev?.date.year !== segment.date.year && (!prev || height > MIN_YEAR_LABEL_DISTANCE)) {
|
||||||
|
segment.hasLabel = true;
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
height += segment.height;
|
||||||
|
prev = segment;
|
||||||
|
return segment;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$: segments = calculateSegments($assetStore.buckets);
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{ scrollTimeline: number }>();
|
const dispatch = createEventDispatcher<{ scrollTimeline: number }>();
|
||||||
const scrollTimeline = () => dispatch('scrollTimeline', toTimelineY(hoverY));
|
const scrollTimeline = () => dispatch('scrollTimeline', toTimelineY(hoverY));
|
||||||
|
@ -67,23 +79,6 @@
|
||||||
isAnimating = false;
|
isAnimating = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const prevYearSegmentHeight = (segments: Segment[], index: number) => {
|
|
||||||
var prevYear = null;
|
|
||||||
var height = 0;
|
|
||||||
for (var i = index; i >= 0; i--) {
|
|
||||||
const curr = segments[i];
|
|
||||||
const currYear = fromLocalDateTime(curr.timeGroup).year;
|
|
||||||
if (prevYear && prevYear != currYear) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
height += curr.height;
|
|
||||||
prevYear = currYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
return height;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerHeight={windowHeight} />
|
<svelte:window bind:innerHeight={windowHeight} />
|
||||||
|
@ -125,11 +120,8 @@
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- Time Segment -->
|
<!-- Time Segment -->
|
||||||
{#each segments as segment, index (segment.timeGroup)}
|
{#each segments as segment}
|
||||||
{@const date = fromLocalDateTime(segment.timeGroup)}
|
{@const label = `${segment.date.toLocaleString({ month: 'short' })} ${segment.date.year}`}
|
||||||
{@const year = date.year}
|
|
||||||
{@const label = `${date.toLocaleString({ month: 'short' })} ${year}`}
|
|
||||||
{@const lastGroupYear = fromLocalDateTime(segments[index - 1]?.timeGroup).year}
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div
|
<div
|
||||||
|
@ -139,12 +131,12 @@
|
||||||
aria-label={segment.timeGroup + ' ' + segment.count}
|
aria-label={segment.timeGroup + ' ' + segment.count}
|
||||||
on:mousemove={() => (hoverLabel = label)}
|
on:mousemove={() => (hoverLabel = label)}
|
||||||
>
|
>
|
||||||
{#if lastGroupYear !== year && (index == 0 || prevYearSegmentHeight(segments, index - 1) > 16)}
|
{#if segment.hasLabel}
|
||||||
<div
|
<div
|
||||||
aria-label={segment.timeGroup + ' ' + segment.count}
|
aria-label={segment.timeGroup + ' ' + segment.count}
|
||||||
class="absolute right-0 z-10 pr-5 text-xs font-medium dark:text-immich-dark-fg font-mono"
|
class="absolute right-0 z-10 pr-5 text-xs font-medium dark:text-immich-dark-fg font-mono"
|
||||||
>
|
>
|
||||||
{year}
|
{segment.date.year}
|
||||||
</div>
|
</div>
|
||||||
{:else if segment.height > 5}
|
{:else if segment.height > 5}
|
||||||
<div
|
<div
|
||||||
|
|
Loading…
Add table
Reference in a new issue