mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
feat(web): add menu bar with action buttons to memory view (#9141)
feat(web): add menu bar with action button to memory lane
This commit is contained in:
parent
13e093b3c2
commit
56a42dad17
1 changed files with 73 additions and 8 deletions
|
@ -3,16 +3,36 @@
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
||||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||||
|
import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte';
|
||||||
|
import ArchiveAction from '$lib/components/photos-page/actions/archive-action.svelte';
|
||||||
|
import CreateSharedLink from '$lib/components/photos-page/actions/create-shared-link.svelte';
|
||||||
|
import DeleteAssets from '$lib/components/photos-page/actions/delete-assets.svelte';
|
||||||
|
import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
|
||||||
|
import FavoriteAction from '$lib/components/photos-page/actions/favorite-action.svelte';
|
||||||
|
import AssetSelectContextMenu from '$lib/components/photos-page/asset-select-context-menu.svelte';
|
||||||
|
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
|
||||||
|
import ChangeDate from '$lib/components/photos-page/actions/change-date-action.svelte';
|
||||||
|
import ChangeLocation from '$lib/components/photos-page/actions/change-location-action.svelte';
|
||||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||||
import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
|
import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte';
|
||||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||||
import type { Viewport } from '$lib/stores/assets.store';
|
import { type Viewport } from '$lib/stores/assets.store';
|
||||||
import { memoryStore } from '$lib/stores/memory.store';
|
import { memoryStore } from '$lib/stores/memory.store';
|
||||||
import { getAssetThumbnailUrl, handlePromiseError, memoryLaneTitle } from '$lib/utils';
|
import { getAssetThumbnailUrl, handlePromiseError, memoryLaneTitle } from '$lib/utils';
|
||||||
import { shortcuts } from '$lib/utils/shortcut';
|
import { shortcuts } from '$lib/utils/shortcut';
|
||||||
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
import { fromLocalDateTime } from '$lib/utils/timeline-util';
|
||||||
import { ThumbnailFormat, getMemoryLane } from '@immich/sdk';
|
import { ThumbnailFormat, getMemoryLane, type AssetResponseDto } from '@immich/sdk';
|
||||||
import { mdiChevronDown, mdiChevronLeft, mdiChevronRight, mdiChevronUp, mdiPause, mdiPlay } from '@mdi/js';
|
import {
|
||||||
|
mdiChevronDown,
|
||||||
|
mdiChevronLeft,
|
||||||
|
mdiChevronRight,
|
||||||
|
mdiChevronUp,
|
||||||
|
mdiDotsVertical,
|
||||||
|
mdiPause,
|
||||||
|
mdiPlay,
|
||||||
|
mdiPlus,
|
||||||
|
mdiSelectAll,
|
||||||
|
} from '@mdi/js';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { tweened } from 'svelte/motion';
|
import { tweened } from 'svelte/motion';
|
||||||
|
@ -74,6 +94,21 @@
|
||||||
// Progress should be reset when the current memory or asset changes.
|
// Progress should be reset when the current memory or asset changes.
|
||||||
$: memoryIndex, assetIndex, handlePromiseError(reset());
|
$: memoryIndex, assetIndex, handlePromiseError(reset());
|
||||||
|
|
||||||
|
let selectedAssets: Set<AssetResponseDto> = new Set();
|
||||||
|
$: isMultiSelectionMode = selectedAssets.size > 0;
|
||||||
|
|
||||||
|
let memoryGallery: HTMLElement;
|
||||||
|
let memoryWrapper: HTMLElement;
|
||||||
|
let galleryInView = false;
|
||||||
|
|
||||||
|
$: isAllArchived = [...selectedAssets].every((asset) => asset.isArchived);
|
||||||
|
$: isAllFavorite = [...selectedAssets].every((asset) => asset.isFavorite);
|
||||||
|
$: {
|
||||||
|
if (!galleryInView) {
|
||||||
|
selectedAssets = new Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!$memoryStore) {
|
if (!$memoryStore) {
|
||||||
const localTime = new Date();
|
const localTime = new Date();
|
||||||
|
@ -84,9 +119,16 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let memoryGallery: HTMLElement;
|
const triggerAssetUpdate = () => (currentMemory.assets = currentMemory.assets);
|
||||||
let memoryWrapper: HTMLElement;
|
|
||||||
let galleryInView = false;
|
const onAssetDelete = (assetIds: string[]) => {
|
||||||
|
const assetIdSet = new Set(assetIds);
|
||||||
|
currentMemory.assets = currentMemory.assets.filter((a: AssetResponseDto) => !assetIdSet.has(a.id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectAll = () => {
|
||||||
|
selectedAssets = new Set(currentMemory.assets);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
|
@ -97,6 +139,30 @@
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{#if isMultiSelectionMode}
|
||||||
|
<div class="sticky top-0 z-[90]">
|
||||||
|
<AssetSelectControlBar assets={selectedAssets} clearSelect={() => (selectedAssets = new Set())}>
|
||||||
|
<CreateSharedLink />
|
||||||
|
<CircleIconButton title="Select all" icon={mdiSelectAll} on:click={handleSelectAll} />
|
||||||
|
|
||||||
|
<AssetSelectContextMenu icon={mdiPlus} title="Add to...">
|
||||||
|
<AddToAlbum />
|
||||||
|
<AddToAlbum shared />
|
||||||
|
</AssetSelectContextMenu>
|
||||||
|
|
||||||
|
<FavoriteAction removeFavorite={isAllFavorite} onFavorite={triggerAssetUpdate} />
|
||||||
|
|
||||||
|
<AssetSelectContextMenu icon={mdiDotsVertical} title="Add">
|
||||||
|
<DownloadAction menuItem />
|
||||||
|
<ChangeDate menuItem />
|
||||||
|
<ChangeLocation menuItem />
|
||||||
|
<ArchiveAction menuItem unarchive={isAllArchived} onArchive={triggerAssetUpdate} />
|
||||||
|
<DeleteAssets menuItem {onAssetDelete} />
|
||||||
|
</AssetSelectContextMenu>
|
||||||
|
</AssetSelectControlBar>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<section id="memory-viewer" class="w-full bg-immich-dark-gray" bind:this={memoryWrapper}>
|
<section id="memory-viewer" class="w-full bg-immich-dark-gray" bind:this={memoryWrapper}>
|
||||||
{#if currentMemory}
|
{#if currentMemory}
|
||||||
<ControlAppBar on:close={() => goto(AppRoute.PHOTOS)} forceDark>
|
<ControlAppBar on:close={() => goto(AppRoute.PHOTOS)} forceDark>
|
||||||
|
@ -268,7 +334,6 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- GALLERY VIEWER -->
|
<!-- GALLERY VIEWER -->
|
||||||
|
|
||||||
<section class="bg-immich-dark-gray m-4">
|
<section class="bg-immich-dark-gray m-4">
|
||||||
<div
|
<div
|
||||||
class="sticky mb-10 mt-4 flex place-content-center place-items-center transition-all"
|
class="sticky mb-10 mt-4 flex place-content-center place-items-center transition-all"
|
||||||
|
@ -292,7 +357,7 @@
|
||||||
bind:clientHeight={viewport.height}
|
bind:clientHeight={viewport.height}
|
||||||
bind:clientWidth={viewport.width}
|
bind:clientWidth={viewport.width}
|
||||||
>
|
>
|
||||||
<GalleryViewer assets={currentMemory.assets} {viewport} />
|
<GalleryViewer assets={currentMemory.assets} {viewport} bind:selectedAssets />
|
||||||
</div>
|
</div>
|
||||||
</IntersectionObserver>
|
</IntersectionObserver>
|
||||||
</section>
|
</section>
|
||||||
|
|
Loading…
Reference in a new issue