From f96816b55fdda2699e0472a741d4f12bf55fcfff Mon Sep 17 00:00:00 2001
From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com>
Date: Tue, 27 Oct 2026 16:24:34 +0100
Subject: [PATCH] refactor(web): bulk (un)archive actions (#32189)
(cherry picked from commit d26c0eec10f1bb49117b71b667c88a8a715b2489)
---
.../gallery-viewer/GalleryViewer.svelte | 16 +---
.../timeline/actions/ArchiveAction.svelte | 54 ------------
.../actions/TimelineKeyboardActions.svelte | 13 +--
.../timeline-manager.svelte.ts | 18 +++-
web/src/lib/services/asset.service.ts | 85 +++++++++++++++++++
web/src/lib/utils/asset-utils.ts | 26 ------
.../[[assetId=id]]/+page.svelte | 8 +-
.../[[assetId=id]]/+page.svelte | 6 +-
.../[[assetId=id]]/+page.svelte | 8 +-
.../[[assetId=id]]/+page.svelte | 6 +-
.../[[assetId=id]]/MapTimelinePanel.svelte | 8 +-
.../[[assetId=id]]/MemoryViewer.svelte | 6 +-
.../[[assetId=id]]/+page.svelte | 11 +--
.../(user)/photos/[[assetId=id]]/+page.svelte | 6 +-
.../[[assetId=id]]/+page.svelte | 7 +-
.../[[assetId=id]]/+page.svelte | 23 ++++-
.../[[assetId=id]]/+page.svelte | 7 +-
17 files changed, 145 insertions(+), 163 deletions(-)
delete mode 100644 web/src/lib/components/timeline/actions/ArchiveAction.svelte
diff --git a/web/src/lib/components/shared-components/gallery-viewer/GalleryViewer.svelte b/web/src/lib/components/shared-components/gallery-viewer/GalleryViewer.svelte
index d1bdeb33e..e017b973a 100644
--- a/web/src/lib/components/shared-components/gallery-viewer/GalleryViewer.svelte
+++ b/web/src/lib/components/shared-components/gallery-viewer/GalleryViewer.svelte
@@ -17,14 +17,14 @@
import { showDeleteModal } from '#lib/stores/preferences.store.ts';
import { handlePromiseError } from '#lib/utils.ts';
import { deleteAssets } from '#lib/utils/actions.ts';
- import { archiveAssets, getNextAsset, getPreviousAsset, navigateToAsset } from '#lib/utils/asset-utils.ts';
+ import { getNextAsset, getPreviousAsset, navigateToAsset } from '#lib/utils/asset-utils.ts';
import { moveFocus } from '#lib/utils/focus-util.ts';
import { handleError } from '#lib/utils/handle-error.ts';
import { getJustifiedLayoutFromAssets } from '#lib/utils/layout-utils.ts';
import { navigate } from '#lib/utils/navigation.ts';
import { isTimelineAsset, toTimelineAsset } from '#lib/utils/timeline-util.ts';
import { TUNABLES } from '#lib/utils/tunables.ts';
- import { AssetVisibility, type AssetResponseDto } from '@immich/sdk';
+ import { type AssetResponseDto } from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { debounce } from 'lodash-es';
import { t } from 'svelte-i18n';
@@ -206,17 +206,6 @@
assetInteraction.clear();
};
- const toggleArchive = async () => {
- const ids = await archiveAssets(
- assetInteraction.assets,
- assetInteraction.isAllArchived ? AssetVisibility.Timeline : AssetVisibility.Archive,
- );
- if (ids) {
- assets = assets.filter((asset) => !ids.includes(asset.id));
- assetInteraction.clear();
- }
- };
-
const focusNextAsset = () => moveFocus((element) => element.dataset.thumbnailFocusContainer !== undefined, 'next');
const focusPreviousAsset = () =>
moveFocus((element) => element.dataset.thumbnailFocusContainer !== undefined, 'previous');
@@ -260,7 +249,6 @@
shortcuts.push(
{ shortcut: { key: 'Delete' }, onShortcut: onDelete },
{ shortcut: { key: 'Delete', shift: true }, onShortcut: () => trashOrDelete(true) },
- { shortcut: { key: 'a', shift: true }, onShortcut: toggleArchive },
);
}
}
diff --git a/web/src/lib/components/timeline/actions/ArchiveAction.svelte b/web/src/lib/components/timeline/actions/ArchiveAction.svelte
deleted file mode 100644
index 36c008730..000000000
--- a/web/src/lib/components/timeline/actions/ArchiveAction.svelte
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-{#if menuItem}
-
-{/if}
-
-{#if !menuItem}
- {#if loading}
- {}}
- />
- {:else}
-
- {/if}
-{/if}
diff --git a/web/src/lib/components/timeline/actions/TimelineKeyboardActions.svelte b/web/src/lib/components/timeline/actions/TimelineKeyboardActions.svelte
index 3daaf8cc6..2e1b938b8 100644
--- a/web/src/lib/components/timeline/actions/TimelineKeyboardActions.svelte
+++ b/web/src/lib/components/timeline/actions/TimelineKeyboardActions.svelte
@@ -7,7 +7,6 @@
} from '#lib/components/timeline/actions/focus-actions.ts';
import type { AssetMultiSelectManager } from '#lib/managers/asset-multi-select-manager.svelte.ts';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.ts';
- import { eventManager } from '#lib/managers/event-manager.svelte.ts';
import { featureFlagsManager } from '#lib/managers/feature-flags-manager.svelte.ts';
import { TimelineManager } from '#lib/managers/timeline-manager/timeline-manager.svelte.ts';
import type { TimelineAsset } from '#lib/managers/timeline-manager/types.ts';
@@ -21,8 +20,7 @@
import { searchStore } from '#lib/stores/search.svelte.ts';
import { handlePromiseError } from '#lib/utils.ts';
import { deleteAssets } from '#lib/utils/actions.ts';
- import { archiveAssets, selectAllAssets } from '#lib/utils/asset-utils.ts';
- import { AssetVisibility } from '@immich/sdk';
+ import { selectAllAssets } from '#lib/utils/asset-utils.ts';
import { isModalOpen, modalManager } from '@immich/ui';
type Props = {
@@ -64,14 +62,6 @@
onEscape?.();
};
- const toggleArchive = async () => {
- const visibility = assetInteraction.isAllArchived ? AssetVisibility.Timeline : AssetVisibility.Archive;
- const ids = await archiveAssets(assetInteraction.assets, visibility);
- timelineManager.update(ids, (asset) => (asset.visibility = visibility));
- eventManager.emit('AssetsArchive', ids);
- assetInteraction.clear();
- };
-
const onSelectStart = (e: Event) => {
if (!searchStore.isSearchEnabled && assetInteraction.selectionActive && keyboardManager.shift) {
e.preventDefault();
@@ -135,7 +125,6 @@
{ shortcut: { key: 'Delete', shift: true }, onShortcut: () => trashOrDelete(true) },
{ shortcut: { key: 'D', ctrl: true }, onShortcut: () => assetInteraction.clear() },
{ shortcut: { key: 's' }, onShortcut: () => onStackAssets() },
- { shortcut: { key: 'a', shift: true }, onShortcut: toggleArchive },
);
} else {
// conflicting shortcuts
diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts
index 9a761ae29..522dcfe07 100644
--- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts
+++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts
@@ -25,7 +25,14 @@ import {
type TimelineDateTime,
type TimelineYearMonth,
} from '#lib/utils/timeline-util.ts';
-import { AssetOrder, AssetOrderBy, getAssetInfo, getTimeBuckets, type AssetResponseDto } from '@immich/sdk';
+import {
+ AssetOrder,
+ AssetOrderBy,
+ AssetVisibility,
+ getAssetInfo,
+ getTimeBuckets,
+ type AssetResponseDto,
+} from '@immich/sdk';
import { clamp, isEqual } from 'lodash-es';
import { SvelteDate, SvelteSet } from 'svelte/reactivity';
import { isMismatched, updateObject } from './internal/utils.svelte';
@@ -122,7 +129,14 @@ export class TimelineManager extends VirtualScrollManager {
this.upsertAssets([timelineAsset]);
}
},
- AssetsUnarchive: (assets) => this.upsertAssets(assets),
+ AssetsArchive: (assetIds) => this.update(assetIds, (asset) => (asset.visibility = AssetVisibility.Archive)),
+ AssetsUnarchive: (assets) => {
+ if (this.#options.visibility === AssetVisibility.Archive) {
+ this.removeAssets(assets.map((asset) => asset.id));
+ } else {
+ this.upsertAssets(assets);
+ }
+ },
AlbumRemoveAssets: ({ assetIds, albumIds }) => {
if (this.#options.albumId && albumIds.includes(this.#options.albumId)) {
this.removeAssets(assetIds);
diff --git a/web/src/lib/services/asset.service.ts b/web/src/lib/services/asset.service.ts
index df25f9060..1f18eedf3 100644
--- a/web/src/lib/services/asset.service.ts
+++ b/web/src/lib/services/asset.service.ts
@@ -3,6 +3,7 @@ import { assetMultiSelectManager } from '#lib/managers/asset-multi-select-manage
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.ts';
import { authManager } from '#lib/managers/auth-manager.svelte.ts';
import { eventManager } from '#lib/managers/event-manager.svelte.ts';
+import type { TimelineAsset } from '#lib/managers/timeline-manager/types.ts';
import AssetAddToAlbumModal from '#lib/modals/AssetAddToAlbumModal.svelte';
import AssetTagModal from '#lib/modals/AssetTagModal.svelte';
import ProfileImageCropperModal from '#lib/modals/ProfileImageCropperModal.svelte';
@@ -25,6 +26,7 @@ import {
getAssetInfo,
runAssetJobs,
updateAsset,
+ updateAssets,
type AlbumResponseDto,
type AssetJobsDto,
type AssetResponseDto,
@@ -33,6 +35,8 @@ import { modalManager, toastManager, type ActionItem } from '@immich/ui';
import {
mdiAccountCircleOutline,
mdiAlertOutline,
+ mdiArchiveArrowDownOutline,
+ mdiArchiveArrowUpOutline,
mdiCogRefreshOutline,
mdiCompare,
mdiContentCopy,
@@ -78,6 +82,19 @@ export const getAssetBulkActions = ($t: MessageFormatter, album?: AlbumResponseD
onAction: () => modalManager.show(AssetAddToAlbumModal, { assetIds }),
};
+ const Archive: ActionItem = {
+ title: $t('to_archive'),
+ icon: mdiArchiveArrowDownOutline,
+ shortcuts: [{ key: 'a', shift: true }],
+ $if: () => assetMultiSelectManager.isAllUserOwned && !assetMultiSelectManager.isAllArchived,
+ onAction: async () => {
+ const assets = ownedAssets.filter((asset) => asset.visibility !== AssetVisibility.Archive);
+ if (await handleSetVisibility(assets, AssetVisibility.Archive)) {
+ assetMultiSelectManager.clear();
+ }
+ },
+ };
+
const CreateSharedLink: ActionItem = {
title: $t('share'),
icon: mdiShareVariantOutline,
@@ -104,6 +121,18 @@ export const getAssetBulkActions = ($t: MessageFormatter, album?: AlbumResponseD
shortcuts: { key: 't' },
};
+ const Unarchive: ActionItem = {
+ title: $t('unarchive'),
+ icon: mdiArchiveArrowUpOutline,
+ shortcuts: [{ key: 'a', shift: true }],
+ $if: () => assetMultiSelectManager.isAllUserOwned && assetMultiSelectManager.isAllArchived,
+ onAction: async () => {
+ if (await handleSetVisibility(ownedAssets, AssetVisibility.Timeline)) {
+ assetMultiSelectManager.clear();
+ }
+ },
+ };
+
const RefreshFacesJob: ActionItem = {
title: $t('refresh_faces'),
icon: mdiHeadSyncOutline,
@@ -131,9 +160,11 @@ export const getAssetBulkActions = ($t: MessageFormatter, album?: AlbumResponseD
return {
AddToAlbum,
+ Archive,
CreateSharedLink,
RemoveFromAlbum,
Tag,
+ Unarchive,
RefreshFacesJob,
RefreshMetadataJob,
RegenerateThumbnailJob,
@@ -500,6 +531,60 @@ export const handleTagAssets = async (assetIds: string[], tagIds: string[]) => {
}
};
+const handleSetVisibility = async (assets: TimelineAsset[], visibility: AssetVisibility) => {
+ const $t = await getFormatter();
+ const ids = assets.map((asset) => asset.id);
+
+ try {
+ await updateAssets({ assetBulkUpdateDto: { ids, visibility } });
+
+ if (visibility === AssetVisibility.Archive) {
+ toastManager.primary({
+ description: $t('archived_count', { values: { count: assets.length } }),
+ button: (close) => ({
+ label: $t('undo'),
+ onclick: () => {
+ close();
+ void undoArchiveAssets(assets);
+ },
+ }),
+ });
+ eventManager.emit('AssetsArchive', ids);
+ } else {
+ // Timeline
+ toastManager.primary($t('unarchived_count', { values: { count: assets.length } }));
+ eventManager.emit('AssetsUnarchive', assets);
+ }
+ } catch (error) {
+ handleError(
+ error,
+ $t('errors.unable_to_archive_unarchive', { values: { archived: visibility === AssetVisibility.Archive } }),
+ );
+ return false;
+ }
+
+ return true;
+};
+
+const undoArchiveAssets = async (assets: TimelineAsset[]) => {
+ const $t = await getFormatter();
+ try {
+ const ids = assets.map((a) => a.id);
+ await updateAssets({
+ assetBulkUpdateDto: { ids, visibility: AssetVisibility.Timeline },
+ });
+
+ for (const asset of assets) {
+ asset.visibility = AssetVisibility.Timeline;
+ }
+ toastManager.success($t('unarchived_count', { values: { count: assets.length } }));
+ eventManager.emit('AssetsUnarchive', assets);
+ eventManager.emit('AssetsUndoArchive', assets);
+ } catch (error) {
+ handleError(error, $t('errors.unable_to_archive_unarchive', { values: { archived: false } }));
+ }
+};
+
const handleBulkRemoveAssetsFromAlbum = async (assetIds: string[], album: AlbumResponseDto) => {
const $t = await getFormatter();
diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts
index f39bd251b..a1e33d72d 100644
--- a/web/src/lib/utils/asset-utils.ts
+++ b/web/src/lib/utils/asset-utils.ts
@@ -337,32 +337,6 @@ const undoArchiveAssets = async (assets: TimelineAsset[]) => {
}
};
-export const archiveAssets = async (assets: TimelineAsset[], visibility: AssetVisibility) => {
- const ids = assets.map(({ id }) => id);
- const $t = get(t);
-
- try {
- if (ids.length > 0) {
- await updateAssets({
- assetBulkUpdateDto: { ids, visibility },
- });
- }
-
- if (visibility === AssetVisibility.Archive) {
- showUndoArchiveToast($t('archived_count', { values: { count: ids.length } }), assets);
- } else {
- toastManager.primary($t('unarchived_count', { values: { count: ids.length } }));
- }
- } catch (error) {
- handleError(
- error,
- $t('errors.unable_to_archive_unarchive', { values: { archived: visibility === AssetVisibility.Archive } }),
- );
- }
-
- return ids;
-};
-
export const delay = async (ms: number) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
index 61143b6ab..f8fb67347 100644
--- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -11,7 +11,6 @@
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import ControlAppBar from '#lib/components/shared-components/ControlAppBar.svelte';
import UserAvatar from '#lib/components/shared-components/UserAvatar.svelte';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '#lib/components/timeline/actions/ChangeDateAction.svelte';
import ChangeDescription from '#lib/components/timeline/actions/ChangeDescriptionAction.svelte';
import ChangeLocation from '#lib/components/timeline/actions/ChangeLocationAction.svelte';
@@ -415,11 +414,8 @@
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+
{/if}
{#if assetMultiSelectManager.assets.length === 1}
diff --git a/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte
index 13ee96640..f8276e5e8 100644
--- a/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -2,7 +2,6 @@
import UserPageLayout from '#lib/components/layouts/UserPageLayout.svelte';
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import EmptyPlaceholder from '#lib/components/shared-components/EmptyPlaceholder.svelte';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import DeleteAssets from '#lib/components/timeline/actions/DeleteAssetsAction.svelte';
import DownloadAction from '#lib/components/timeline/actions/DownloadAction.svelte';
import FavoriteAction from '#lib/components/timeline/actions/FavoriteAction.svelte';
@@ -63,10 +62,7 @@
{const Actions = $derived(getAssetBulkActions($t))}
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
diff --git a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte
index 1e9131d10..cf07c1c17 100644
--- a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -3,7 +3,6 @@
import UserPageLayout from '#lib/components/layouts/UserPageLayout.svelte';
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import EmptyPlaceholder from '#lib/components/shared-components/EmptyPlaceholder.svelte';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '#lib/components/timeline/actions/ChangeDateAction.svelte';
import ChangeDescription from '#lib/components/timeline/actions/ChangeDescriptionAction.svelte';
import ChangeLocation from '#lib/components/timeline/actions/ChangeLocationAction.svelte';
@@ -75,11 +74,8 @@
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+
{/snippet}
-
+
@@ -168,7 +167,8 @@
-
+
+
diff --git a/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/MapTimelinePanel.svelte b/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/MapTimelinePanel.svelte
index 18de77a56..df26d7e16 100644
--- a/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/MapTimelinePanel.svelte
+++ b/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/MapTimelinePanel.svelte
@@ -2,7 +2,6 @@
import ActionMenuItem from '#lib/components/ActionMenuItem.svelte';
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import type { SelectionBBox } from '#lib/components/shared-components/map/types.ts';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '#lib/components/timeline/actions/ChangeDateAction.svelte';
import ChangeDescription from '#lib/components/timeline/actions/ChangeDescriptionAction.svelte';
import ChangeLocation from '#lib/components/timeline/actions/ChangeLocationAction.svelte';
@@ -146,11 +145,8 @@
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+
+
+
{#if assetMultiSelectManager.selectionActive}
@@ -299,7 +301,7 @@
-
+
diff --git a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte
index a32fdf477..4b82c65dc 100644
--- a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -8,7 +8,6 @@
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import ControlAppBar from '#lib/components/shared-components/ControlAppBar.svelte';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '#lib/components/timeline/actions/ChangeDateAction.svelte';
import ChangeDescription from '#lib/components/timeline/actions/ChangeDescriptionAction.svelte';
import ChangeLocation from '#lib/components/timeline/actions/ChangeLocationAction.svelte';
@@ -500,14 +499,8 @@
-
- timelineManager.update(ids, (asset) => {
- asset.visibility = visibility;
- })}
- />
+
+
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+
{
+ if (!terms.visibility || terms.visibility === AssetVisibility.Timeline) {
+ const assetIdSet = new Set(assetIds);
+ searchResultAssets = searchResultAssets.filter((asset) => !assetIdSet.has(asset.id));
+ }
+ };
+
+ // TODO: add back in opposite case
+ const onAssetsUnarchive = (assets: TimelineAsset[]) => {
+ if (terms.visibility === AssetVisibility.Archive) {
+ const assetIdSet = new Set(assets.map((asset) => asset.id));
+ searchResultAssets = searchResultAssets.filter((asset) => !assetIdSet.has(asset.id));
+ }
+ };
+
function getObjectKeys(obj: T): (keyof T)[] {
return Object.keys(obj) as (keyof T)[];
}
@@ -254,7 +268,7 @@
-
+
{#if searchTermKeys.length > 0}
@@ -377,7 +391,8 @@
-
+
+
diff --git a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte
index f329853a2..422968461 100644
--- a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -10,7 +10,6 @@
import Sidebar from '#lib/components/sidebar/Sidebar.svelte';
import AssetSelectControlBar from '#lib/components/timeline/AssetSelectControlBar.svelte';
import Timeline from '#lib/components/timeline/Timeline.svelte';
- import ArchiveAction from '#lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '#lib/components/timeline/actions/ChangeDateAction.svelte';
import ChangeDescription from '#lib/components/timeline/actions/ChangeDescriptionAction.svelte';
import ChangeLocation from '#lib/components/timeline/actions/ChangeLocationAction.svelte';
@@ -134,10 +133,8 @@
- timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
- />
+
+