Rename asset-grid to base-timeline and reorganize timeline components

• Rename asset-grid.svelte to base-timeline.svelte
• Move asset-grid-actions.svelte to timeline-keyboard-actions.svelte in timeline-viewer/actions/
• Move delete-asset-dialog.svelte to timeline-viewer/actions/
• Update all imports across routes and components
This commit is contained in:
midzelis
2025-08-14 21:36:22 +00:00
parent 8465ce5a22
commit 521825e5e6
18 changed files with 254 additions and 46 deletions
@@ -18,10 +18,10 @@
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import DownloadAction from '../photos-page/actions/download-action.svelte'; import DownloadAction from '../photos-page/actions/download-action.svelte';
import AssetGrid from '../photos-page/asset-grid.svelte';
import ControlAppBar from '../shared-components/control-app-bar.svelte'; import ControlAppBar from '../shared-components/control-app-bar.svelte';
import ImmichLogoSmallLink from '../shared-components/immich-logo-small-link.svelte'; import ImmichLogoSmallLink from '../shared-components/immich-logo-small-link.svelte';
import ThemeButton from '../shared-components/theme-button.svelte'; import ThemeButton from '../shared-components/theme-button.svelte';
import AssetGrid from '../timeline-viewer/base-timeline.svelte';
import AlbumSummary from './album-summary.svelte'; import AlbumSummary from './album-summary.svelte';
interface Props { interface Props {
@@ -1,21 +1,21 @@
<script lang="ts"> <script lang="ts">
import { shortcuts } from '$lib/actions/shortcut'; import { shortcuts } from '$lib/actions/shortcut';
import DeleteAssetDialog from '$lib/components/photos-page/delete-asset-dialog.svelte';
import { import {
NotificationType, NotificationType,
notificationController, notificationController,
} from '$lib/components/shared-components/notification/notification'; } from '$lib/components/shared-components/notification/notification';
import Portal from '$lib/components/shared-components/portal/portal.svelte'; import Portal from '$lib/components/shared-components/portal/portal.svelte';
import DeleteAssetDialog from '$lib/components/timeline-viewer/actions/delete-asset-dialog.svelte';
import { AssetAction } from '$lib/constants'; import { AssetAction } from '$lib/constants';
import { showDeleteModal } from '$lib/stores/preferences.store'; import { showDeleteModal } from '$lib/stores/preferences.store';
import { featureFlags } from '$lib/stores/server-config.store'; import { featureFlags } from '$lib/stores/server-config.store';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { toTimelineAsset } from '$lib/utils/timeline-util'; import { toTimelineAsset } from '$lib/utils/timeline-util';
import { deleteAssets, type AssetResponseDto } from '@immich/sdk'; import { deleteAssets, type AssetResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js'; import { mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import type { OnAction, PreAction } from './action'; import type { OnAction, PreAction } from './action';
import { IconButton } from '@immich/ui';
interface Props { interface Props {
asset: AssetResponseDto; asset: AssetResponseDto;
@@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { featureFlags } from '$lib/stores/server-config.store'; import { featureFlags } from '$lib/stores/server-config.store';
import { type OnDelete, type OnUndoDelete, deleteAssets } from '$lib/utils/actions'; import { type OnDelete, type OnUndoDelete, deleteAssets } from '$lib/utils/actions';
import { IconButton } from '@immich/ui';
import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js'; import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte'; import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
import DeleteAssetDialog from '../../timeline-viewer/actions/delete-asset-dialog.svelte';
import { getAssetControlContext } from '../asset-select-control-bar.svelte'; import { getAssetControlContext } from '../asset-select-control-bar.svelte';
import DeleteAssetDialog from '../delete-asset-dialog.svelte';
import { IconButton } from '@immich/ui';
interface Props { interface Props {
onAssetDelete: OnDelete; onAssetDelete: OnDelete;
@@ -12,6 +12,7 @@
import Scrubber from '../shared-components/scrubber/scrubber.svelte'; import Scrubber from '../shared-components/scrubber/scrubber.svelte';
interface Props { interface Props {
customLayout?: Snippet<[TimelineAsset]>;
isSelectionMode?: boolean; isSelectionMode?: boolean;
singleSelect?: boolean; singleSelect?: boolean;
/** `true` if this asset grid is responds to navigation events; if `true`, then look at the /** `true` if this asset grid is responds to navigation events; if `true`, then look at the
@@ -32,25 +33,26 @@
album?: AlbumResponseDto | null; album?: AlbumResponseDto | null;
person?: PersonResponseDto | null; person?: PersonResponseDto | null;
isShowDeleteConfirmation?: boolean; isShowDeleteConfirmation?: boolean;
/**
* Customizes what happens when an asset is opened (clicked/tapped).
*
* @param dayGroup - The day group containing the asset
* @param asset - The asset that was opened
* @param defaultAssetOpen - Callback that executes the default behavior:
* - If selection mode is active: Selects/deselects the asset
* - If selection mode is inactive: Navigates to the asset detail view
*
* If not provided, the default behavior is used automatically.
*/
onAssetOpen?: (dayGroup: DayGroup, asset: TimelineAsset, defaultAssetOpen: () => void) => void;
onSelect?: (asset: TimelineAsset) => void; onSelect?: (asset: TimelineAsset) => void;
onEscape?: () => void; onEscape?: () => void;
children?: Snippet; children?: Snippet;
empty?: Snippet; empty?: Snippet;
customLayout?: Snippet<[TimelineAsset]>;
onThumbnailClick?: (
asset: TimelineAsset,
timelineManager: TimelineManager,
dayGroup: DayGroup,
onClick: (
timelineManager: TimelineManager,
assets: TimelineAsset[],
groupTitle: string,
asset: TimelineAsset,
) => void,
) => void;
} }
let { let {
customLayout,
isSelectionMode = false, isSelectionMode = false,
singleSelect = false, singleSelect = false,
enableRouting, enableRouting,
@@ -63,12 +65,11 @@
album = null, album = null,
person = null, person = null,
isShowDeleteConfirmation = $bindable(false), isShowDeleteConfirmation = $bindable(false),
onAssetOpen,
onSelect = () => {}, onSelect = () => {},
onEscape = () => {}, onEscape = () => {},
children, children,
empty, empty,
customLayout,
onThumbnailClick,
}: Props = $props(); }: Props = $props();
let leadout = $state(false); let leadout = $state(false);
@@ -186,6 +187,7 @@
</script> </script>
<TimelineViewer <TimelineViewer
{customLayout}
{isSelectionMode} {isSelectionMode}
{singleSelect} {singleSelect}
{enableRouting} {enableRouting}
@@ -198,6 +200,7 @@
{album} {album}
{person} {person}
{isShowDeleteConfirmation} {isShowDeleteConfirmation}
{onAssetOpen}
{onSelect} {onSelect}
{onEscape} {onEscape}
{children} {children}
@@ -23,7 +23,7 @@
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import AssetViewer from '../../asset-viewer/asset-viewer.svelte'; import AssetViewer from '../../asset-viewer/asset-viewer.svelte';
import DeleteAssetDialog from '../../photos-page/delete-asset-dialog.svelte'; import DeleteAssetDialog from '../../timeline-viewer/actions/delete-asset-dialog.svelte';
import Portal from '../portal/portal.svelte'; import Portal from '../portal/portal.svelte';
interface Props { interface Props {
@@ -129,9 +129,9 @@
} }
}; };
const isTrashEnabled = $derived($featureFlags.loaded && $featureFlags.trash); let isTrashEnabled = $derived($featureFlags.loaded && $featureFlags.trash);
const isEmpty = $derived(timelineManager.isInitialized && timelineManager.months.length === 0); let isEmpty = $derived(timelineManager.isInitialized && timelineManager.months.length === 0);
const idsSelectedAssets = $derived(assetInteraction.selectedAssets.map(({ id }) => id)); let idsSelectedAssets = $derived(assetInteraction.selectedAssets.map(({ id }) => id));
let isShortcutModalOpen = false; let isShortcutModalOpen = false;
const handleOpenShortcutModal = async () => { const handleOpenShortcutModal = async () => {
@@ -0,0 +1,208 @@
<script lang="ts">
import TimelineViewer from '$lib/components/timeline-viewer/timeline-viewer.svelte';
import { AssetAction } from '$lib/constants';
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
import type { ScrubberListener } from '$lib/utils/timeline-util';
import type { AlbumResponseDto, PersonResponseDto } from '@immich/sdk';
import type { Snippet } from 'svelte';
import Scrubber from '../shared-components/scrubber/scrubber.svelte';
interface Props {
isSelectionMode?: boolean;
singleSelect?: boolean;
/** `true` if this asset grid is responds to navigation events; if `true`, then look at the
`AssetViewingStore.gridScrollTarget` and load and scroll to the asset specified, and
additionally, update the page location/url with the asset as the asset-grid is scrolled */
enableRouting: boolean;
timelineManager: TimelineManager;
assetInteraction: AssetInteraction;
removeAction?:
| AssetAction.UNARCHIVE
| AssetAction.ARCHIVE
| AssetAction.FAVORITE
| AssetAction.UNFAVORITE
| AssetAction.SET_VISIBILITY_TIMELINE;
withStacked?: boolean;
showArchiveIcon?: boolean;
isShared?: boolean;
album?: AlbumResponseDto | null;
person?: PersonResponseDto | null;
isShowDeleteConfirmation?: boolean;
onSelect?: (asset: TimelineAsset) => void;
onEscape?: () => void;
children?: Snippet;
empty?: Snippet;
}
let {
isSelectionMode = false,
singleSelect = false,
enableRouting,
timelineManager = $bindable(),
assetInteraction,
removeAction,
withStacked = false,
showArchiveIcon = false,
isShared = false,
album = null,
person = null,
isShowDeleteConfirmation = $bindable(false),
onSelect = () => {},
onEscape = () => {},
children,
empty,
}: Props = $props();
let leadout = $state(false);
let scrubberMonthPercent = $state(0);
let scrubberMonth: { year: number; month: number } | undefined = $state(undefined);
let scrubOverallPercent: number = $state(0);
let scrubberWidth: number = $state(0);
// note: don't throttle, debounch, or otherwise make this function async - it causes flicker
// this function updates the scrubber position based on the current scroll position in the timeline
const handleTimelineScroll = () => {
leadout = false;
if (timelineManager.timelineHeight < timelineManager.viewportHeight * 2) {
// edge case - scroll limited due to size of content, must adjust - use the overall percent instead
const maxScroll = timelineManager.getMaxScroll();
scrubOverallPercent = Math.min(1, timelineManager.visibleWindow.top / maxScroll);
scrubberMonth = undefined;
scrubberMonthPercent = 0;
} else {
let top = timelineManager.visibleWindow.top;
if (top < timelineManager.topSectionHeight) {
// in the lead-in area
scrubberMonth = undefined;
scrubberMonthPercent = 0;
const maxScroll = timelineManager.getMaxScroll();
scrubOverallPercent = Math.min(1, top / maxScroll);
return;
}
let maxScrollPercent = timelineManager.getMaxScrollPercent();
let found = false;
const monthsLength = timelineManager.months.length;
for (let i = -1; i < monthsLength + 1; i++) {
let monthGroup: TimelineYearMonth | undefined;
let monthGroupHeight = 0;
if (i === -1) {
// lead-in
monthGroupHeight = timelineManager.topSectionHeight;
} else if (i === monthsLength) {
// lead-out
monthGroupHeight = timelineManager.bottomSectionHeight;
} else {
monthGroup = timelineManager.months[i].yearMonth;
monthGroupHeight = timelineManager.months[i].height;
}
let next = top - monthGroupHeight * maxScrollPercent;
// instead of checking for < 0, add a little wiggle room for subpixel resolution
if (next < -1 && monthGroup) {
scrubberMonth = monthGroup;
// allowing next to be at least 1 may cause percent to go negative, so ensure positive percentage
scrubberMonthPercent = Math.max(0, top / (monthGroupHeight * maxScrollPercent));
// compensate for lost precision/rounding errors advance to the next bucket, if present
if (scrubberMonthPercent > 0.9999 && i + 1 < monthsLength - 1) {
scrubberMonth = timelineManager.months[i + 1].yearMonth;
scrubberMonthPercent = 0;
}
found = true;
break;
}
top = next;
}
if (!found) {
leadout = true;
scrubberMonth = undefined;
scrubberMonthPercent = 0;
scrubOverallPercent = 1;
}
}
};
// note: don't throttle, debounch, or otherwise make this function async - it causes flicker
// this function scrolls the timeline to the specified month group and offset, based on scrubber interaction
const onScrub: ScrubberListener = ({
scrubberMonth,
overallScrollPercent,
scrubberMonthScrollPercent,
handleScrollTop,
}) => {
if (!scrubberMonth || timelineManager.timelineHeight < timelineManager.viewportHeight * 2) {
// edge case - scroll limited due to size of content, must adjust - use use the overall percent instead
const maxScroll = timelineManager.getMaxScroll();
const offset = maxScroll * overallScrollPercent;
handleScrollTop?.(offset);
} else {
const monthGroup = timelineManager.months.find(
({ yearMonth: { year, month } }) => year === scrubberMonth.year && month === scrubberMonth.month,
);
if (!monthGroup) {
return;
}
scrollToMonthGroupAndOffset(monthGroup, scrubberMonthScrollPercent, handleScrollTop);
}
};
const scrollToMonthGroupAndOffset = (
monthGroup: MonthGroup,
monthGroupScrollPercent: number,
handleScrollTop?: (top: number) => void,
) => {
const topOffset = monthGroup.top;
const maxScrollPercent = timelineManager.getMaxScrollPercent();
const delta = monthGroup.height * monthGroupScrollPercent;
const scrollToTop = (topOffset + delta) * maxScrollPercent;
handleScrollTop?.(scrollToTop);
};
</script>
<TimelineViewer
{isSelectionMode}
{singleSelect}
{enableRouting}
{timelineManager}
{assetInteraction}
{removeAction}
{withStacked}
{showArchiveIcon}
{isShared}
{album}
{person}
{isShowDeleteConfirmation}
{onSelect}
{onEscape}
{children}
{empty}
{handleTimelineScroll}
>
{#snippet header(handleScrollTop)}
{#if timelineManager.months.length > 0}
<Scrubber
{timelineManager}
height={timelineManager.viewportHeight}
timelineTopOffset={timelineManager.topSectionHeight}
timelineBottomOffset={timelineManager.bottomSectionHeight}
{leadout}
{scrubOverallPercent}
{scrubberMonthPercent}
{scrubberMonth}
onScrub={(args) => onScrub({ ...args, handleScrollTop })}
bind:scrubberWidth
/>
{/if}
{/snippet}
</TimelineViewer>
@@ -2,11 +2,12 @@
import { afterNavigate, beforeNavigate } from '$app/navigation'; import { afterNavigate, beforeNavigate } from '$app/navigation';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer'; import { resizeObserver, type OnResizeCallback } from '$lib/actions/resize-observer';
import AssetGridActions from '$lib/components/photos-page/asset-grid-actions.svelte'; import AssetGridActions from '$lib/components/timeline-viewer/actions/timeline-keyboard-actions.svelte';
import Skeleton from '$lib/components/timeline-viewer/skeleton.svelte'; import Skeleton from '$lib/components/timeline-viewer/skeleton.svelte';
import TimelineAssetViewer from '$lib/components/timeline-viewer/timeline-asset-viewer.svelte'; import TimelineAssetViewer from '$lib/components/timeline-viewer/timeline-asset-viewer.svelte';
import SelectableTimelineDay from '$lib/components/timeline-viewer/timeline-day/selectable-timeline-day.svelte'; import SelectableTimelineDay from '$lib/components/timeline-viewer/timeline-day/selectable-timeline-day.svelte';
import { AssetAction } from '$lib/constants'; import { AssetAction } from '$lib/constants';
import type { DayGroup } from '$lib/managers/timeline-manager/day-group.svelte';
import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte'; import type { MonthGroup } from '$lib/managers/timeline-manager/month-group.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
@@ -20,6 +21,7 @@
import Portal from '../shared-components/portal/portal.svelte'; import Portal from '../shared-components/portal/portal.svelte';
interface Props { interface Props {
customLayout?: Snippet<[TimelineAsset]>;
isSelectionMode?: boolean; isSelectionMode?: boolean;
singleSelect?: boolean; singleSelect?: boolean;
/** `true` if this asset grid is responds to navigation events; if `true`, then look at the /** `true` if this asset grid is responds to navigation events; if `true`, then look at the
@@ -40,6 +42,7 @@
album?: AlbumResponseDto | null; album?: AlbumResponseDto | null;
person?: PersonResponseDto | null; person?: PersonResponseDto | null;
isShowDeleteConfirmation?: boolean; isShowDeleteConfirmation?: boolean;
onAssetOpen?: (dayGroup: DayGroup, asset: TimelineAsset, defaultAssetOpen: () => void) => void;
onSelect?: (asset: TimelineAsset) => void; onSelect?: (asset: TimelineAsset) => void;
onEscape?: () => void; onEscape?: () => void;
header?: Snippet<[handleScrollTop: (top: number) => void]>; header?: Snippet<[handleScrollTop: (top: number) => void]>;
@@ -49,6 +52,7 @@
} }
let { let {
customLayout,
isSelectionMode = false, isSelectionMode = false,
singleSelect = false, singleSelect = false,
enableRouting, enableRouting,
@@ -61,6 +65,7 @@
album = null, album = null,
person = null, person = null,
isShowDeleteConfirmation = $bindable(false), isShowDeleteConfirmation = $bindable(false),
onAssetOpen,
onSelect = (asset: TimelineAsset) => void 0, onSelect = (asset: TimelineAsset) => void 0,
onEscape = () => {}, onEscape = () => {},
children, children,
@@ -317,6 +322,7 @@
style:width="100%" style:width="100%"
> >
<SelectableTimelineDay <SelectableTimelineDay
{customLayout}
{withStacked} {withStacked}
{showArchiveIcon} {showArchiveIcon}
{assetInteraction} {assetInteraction}
@@ -324,6 +330,7 @@
{isSelectionMode} {isSelectionMode}
{singleSelect} {singleSelect}
{monthGroup} {monthGroup}
{onAssetOpen}
{onSelect} {onSelect}
{onScrollToTop} {onScrollToTop}
{onScrollCompensation} {onScrollCompensation}
@@ -22,7 +22,6 @@
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; import TagAction from '$lib/components/photos-page/actions/tag-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
@@ -32,6 +31,7 @@
notificationController, notificationController,
} from '$lib/components/shared-components/notification/notification'; } from '$lib/components/shared-components/notification/notification';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte'; import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AlbumPageViewMode, AppRoute } from '$lib/constants'; import { AlbumPageViewMode, AppRoute } from '$lib/constants';
import { activityManager } from '$lib/managers/activity-manager.svelte'; import { activityManager } from '$lib/managers/activity-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
@@ -7,10 +7,10 @@
import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte'; import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
import FavoriteAction from '$lib/components/photos-page/actions/favorite-action.svelte'; import FavoriteAction from '$lib/components/photos-page/actions/favorite-action.svelte';
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AssetAction } from '$lib/constants'; import { AssetAction } from '$lib/constants';
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
@@ -12,10 +12,10 @@
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; import TagAction from '$lib/components/photos-page/actions/tag-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AssetAction } from '$lib/constants'; import { AssetAction } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -7,10 +7,10 @@
import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte'; import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AppRoute, AssetAction } from '$lib/constants'; import { AppRoute, AssetAction } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -3,10 +3,10 @@
import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte'; import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte';
import CreateSharedLink from '$lib/components/photos-page/actions/create-shared-link.svelte'; import CreateSharedLink from '$lib/components/photos-page/actions/create-shared-link.svelte';
import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte'; import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AppRoute } from '$lib/constants'; import { AppRoute } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -20,7 +20,6 @@
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; import TagAction from '$lib/components/photos-page/actions/tag-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
@@ -30,6 +29,7 @@
NotificationType, NotificationType,
notificationController, notificationController,
} from '$lib/components/shared-components/notification/notification'; } from '$lib/components/shared-components/notification/notification';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AppRoute, PersonPageViewMode, QueryParameter, SessionStorageKey } from '$lib/constants'; import { AppRoute, PersonPageViewMode, QueryParameter, SessionStorageKey } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types'; import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
@@ -16,11 +16,11 @@
import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte';
import StackAction from '$lib/components/photos-page/actions/stack-action.svelte'; import StackAction from '$lib/components/photos-page/actions/stack-action.svelte';
import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; import TagAction from '$lib/components/photos-page/actions/tag-action.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import MemoryLane from '$lib/components/photos-page/memory-lane.svelte'; import MemoryLane from '$lib/components/photos-page/memory-lane.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AssetAction } from '$lib/constants'; import { AssetAction } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -5,13 +5,13 @@
import DeleteAssets from '$lib/components/photos-page/actions/delete-assets.svelte'; import DeleteAssets from '$lib/components/photos-page/actions/delete-assets.svelte';
import RestoreAssets from '$lib/components/photos-page/actions/restore-assets.svelte'; import RestoreAssets from '$lib/components/photos-page/actions/restore-assets.svelte';
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import { import {
notificationController, notificationController,
NotificationType, NotificationType,
} from '$lib/components/shared-components/notification/notification'; } from '$lib/components/shared-components/notification/notification';
import AssetGrid from '$lib/components/timeline-viewer/base-timeline.svelte';
import { AppRoute } from '$lib/constants'; import { AppRoute } from '$lib/constants';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
@@ -110,17 +110,7 @@
return !!asset.latitude && !!asset.longitude; return !!asset.latitude && !!asset.longitude;
}; };
const handleThumbnailClick = ( const handleOnAssetOpen = (dayGroup: DayGroup, asset: TimelineAsset, defaultAssetOpen: () => void) => {
asset: TimelineAsset,
timelineManager: TimelineManager,
dayGroup: DayGroup,
onClick: (
timelineManager: TimelineManager,
assets: TimelineAsset[],
groupTitle: string,
asset: TimelineAsset,
) => void,
) => {
if (hasGps(asset)) { if (hasGps(asset)) {
locationUpdated = true; locationUpdated = true;
setTimeout(() => { setTimeout(() => {
@@ -128,9 +118,9 @@
}, 1500); }, 1500);
location = { latitude: asset.latitude!, longitude: asset.longitude! }; location = { latitude: asset.latitude!, longitude: asset.longitude! };
void setQueryValue('at', asset.id); void setQueryValue('at', asset.id);
} else { return;
onClick(timelineManager, dayGroup.getAssets(), dayGroup.groupTitle, asset);
} }
defaultAssetOpen();
}; };
</script> </script>
@@ -193,7 +183,7 @@
removeAction={AssetAction.ARCHIVE} removeAction={AssetAction.ARCHIVE}
onEscape={handleEscape} onEscape={handleEscape}
withStacked withStacked
onThumbnailClick={handleThumbnailClick} onAssetOpen={handleOnAssetOpen}
> >
{#snippet customLayout(asset: TimelineAsset)} {#snippet customLayout(asset: TimelineAsset)}
{#if hasGps(asset)} {#if hasGps(asset)}