mirror of
https://github.com/immich-app/immich.git
synced 2024-12-28 22:51:59 +00:00
feat(web): scrubber label and animation (#13815)
* feat(web): scrubber label and animation * tune x fly in distance * refactor * lint and minor fix * fly height
This commit is contained in:
parent
0d62ff11f1
commit
244c8cb4d4
3 changed files with 34 additions and 4 deletions
|
@ -36,6 +36,7 @@
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import type { UpdatePayload } from 'vite';
|
import type { UpdatePayload } from 'vite';
|
||||||
import { generateId } from '$lib/utils/generate-id';
|
import { generateId } from '$lib/utils/generate-id';
|
||||||
|
import { isTimelineScrolling } from '$lib/stores/timeline.store';
|
||||||
|
|
||||||
export let isSelectionMode = false;
|
export let isSelectionMode = false;
|
||||||
export let singleSelect = false;
|
export let singleSelect = false;
|
||||||
|
@ -331,7 +332,17 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let scrollObserverTimer: NodeJS.Timeout;
|
||||||
|
|
||||||
const _handleTimelineScroll = () => {
|
const _handleTimelineScroll = () => {
|
||||||
|
$isTimelineScrolling = true;
|
||||||
|
if (scrollObserverTimer) {
|
||||||
|
clearTimeout(scrollObserverTimer);
|
||||||
|
}
|
||||||
|
scrollObserverTimer = setTimeout(() => {
|
||||||
|
$isTimelineScrolling = false;
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
leadout = false;
|
leadout = false;
|
||||||
if ($assetStore.timelineHeight < safeViewport.height * 2) {
|
if ($assetStore.timelineHeight < safeViewport.height * 2) {
|
||||||
// edge case - scroll limited due to size of content, must adjust - use the overall percent instead
|
// edge case - scroll limited due to size of content, must adjust - use the overall percent instead
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { AssetStore, AssetBucket, BucketListener } from '$lib/stores/assets.store';
|
import type { AssetStore, AssetBucket, BucketListener } from '$lib/stores/assets.store';
|
||||||
import type { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { fromLocalDateTime, type ScrubberListener } from '$lib/utils/timeline-util';
|
import { fromLocalDateTime, type ScrubberListener } from '$lib/utils/timeline-util';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { isTimelineScrolling } from '$lib/stores/timeline.store';
|
||||||
|
import { parseUtcDate } from '$lib/utils/date-time';
|
||||||
|
import { fly } from 'svelte/transition';
|
||||||
|
|
||||||
export let timelineTopOffset = 0;
|
export let timelineTopOffset = 0;
|
||||||
export let timelineBottomOffset = 0;
|
export let timelineBottomOffset = 0;
|
||||||
|
@ -72,6 +75,7 @@
|
||||||
$: timelineFullHeight = $assetStore.timelineHeight + timelineTopOffset + timelineBottomOffset;
|
$: timelineFullHeight = $assetStore.timelineHeight + timelineTopOffset + timelineBottomOffset;
|
||||||
$: relativeTopOffset = toScrollY(timelineTopOffset / timelineFullHeight);
|
$: relativeTopOffset = toScrollY(timelineTopOffset / timelineFullHeight);
|
||||||
$: relativeBottomOffset = toScrollY(timelineBottomOffset / timelineFullHeight);
|
$: relativeBottomOffset = toScrollY(timelineBottomOffset / timelineFullHeight);
|
||||||
|
$: formatedDate = scrubBucket?.bucketDate ? parseUtcDate(scrubBucket?.bucketDate).toFormat('MMM yyyy') : '';
|
||||||
|
|
||||||
const listener: BucketListener = (event) => {
|
const listener: BucketListener = (event) => {
|
||||||
const { type } = event;
|
const { type } = event;
|
||||||
|
@ -210,8 +214,9 @@
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
transition:fly={{ x: 50, duration: 250 }}
|
||||||
id="immich-scrubbable-scrollbar"
|
id="immich-scrubbable-scrollbar"
|
||||||
class={`absolute right-0 z-[1] select-none bg-immich-bg hover:cursor-row-resize`}
|
class="absolute right-0 z-[1] select-none bg-immich-bg hover:cursor-row-resize"
|
||||||
style:padding-top={HOVER_DATE_HEIGHT + 'px'}
|
style:padding-top={HOVER_DATE_HEIGHT + 'px'}
|
||||||
style:padding-bottom={HOVER_DATE_HEIGHT + 'px'}
|
style:padding-bottom={HOVER_DATE_HEIGHT + 'px'}
|
||||||
class:invisible
|
class:invisible
|
||||||
|
@ -235,9 +240,20 @@
|
||||||
<!-- Scroll Position Indicator Line -->
|
<!-- Scroll Position Indicator Line -->
|
||||||
{#if !isDragging}
|
{#if !isDragging}
|
||||||
<div
|
<div
|
||||||
class="absolute right-0 h-[2px] w-10 bg-immich-primary dark:bg-immich-dark-primary"
|
class="absolute right-0 {$isTimelineScrolling && formatedDate
|
||||||
|
? 'h-[0px]'
|
||||||
|
: 'h-[2px]'} w-10 bg-immich-primary dark:bg-immich-dark-primary"
|
||||||
style:top="{scrollY + HOVER_DATE_HEIGHT}px"
|
style:top="{scrollY + HOVER_DATE_HEIGHT}px"
|
||||||
/>
|
>
|
||||||
|
{#if $isTimelineScrolling && formatedDate}
|
||||||
|
<p
|
||||||
|
transition:fly={{ y: -15, duration: 350 }}
|
||||||
|
class="truncate opacity-85 pointer-events-none absolute right-0 bottom-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-b-2 border-immich-primary bg-immich-bg py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||||
|
>
|
||||||
|
{formatedDate}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div id="lead-in" class="relative" style:height={relativeTopOffset + 'px'} data-label={segments.at(0)?.dateFormatted}>
|
<div id="lead-in" class="relative" style:height={relativeTopOffset + 'px'} data-label={segments.at(0)?.dateFormatted}>
|
||||||
{#if relativeTopOffset > 6}
|
{#if relativeTopOffset > 6}
|
||||||
|
|
3
web/src/lib/stores/timeline.store.ts
Normal file
3
web/src/lib/stores/timeline.store.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export const isTimelineScrolling = writable(false);
|
Loading…
Reference in a new issue