refactor(web): bulk (un)archive actions (#32189)
(cherry picked from commit d26c0eec10f1bb49117b71b667c88a8a715b2489)
This commit is contained in:
@@ -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 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<script lang="ts">
|
||||
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
|
||||
import { assetMultiSelectManager } from '#lib/managers/asset-multi-select-manager.svelte.ts';
|
||||
import type { OnArchive } from '#lib/utils/actions.ts';
|
||||
import { archiveAssets } from '#lib/utils/asset-utils.ts';
|
||||
import { AssetVisibility } from '@immich/sdk';
|
||||
import { IconButton } from '@immich/ui';
|
||||
import { mdiArchiveArrowDownOutline, mdiArchiveArrowUpOutline, mdiTimerSand } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
type Props = {
|
||||
onArchive?: OnArchive;
|
||||
menuItem?: boolean;
|
||||
unarchive?: boolean;
|
||||
};
|
||||
|
||||
let { onArchive, menuItem = false, unarchive = false }: Props = $props();
|
||||
|
||||
let text = $derived(unarchive ? $t('unarchive') : $t('to_archive'));
|
||||
let icon = $derived(unarchive ? mdiArchiveArrowUpOutline : mdiArchiveArrowDownOutline);
|
||||
|
||||
let loading = $state(false);
|
||||
|
||||
const handleArchive = async () => {
|
||||
const visibility = unarchive ? AssetVisibility.Timeline : AssetVisibility.Archive;
|
||||
const assets = assetMultiSelectManager.getOwnedAssets().filter((asset) => asset.visibility !== visibility);
|
||||
loading = true;
|
||||
const ids = await archiveAssets(assets, visibility as AssetVisibility);
|
||||
if (ids) {
|
||||
onArchive?.(ids, visibility);
|
||||
assetMultiSelectManager.clear();
|
||||
}
|
||||
loading = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if menuItem}
|
||||
<MenuOption {text} {icon} onClick={handleArchive} />
|
||||
{/if}
|
||||
|
||||
{#if !menuItem}
|
||||
{#if loading}
|
||||
<IconButton
|
||||
shape="round"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
aria-label={$t('loading')}
|
||||
icon={mdiTimerSand}
|
||||
onclick={() => {}}
|
||||
/>
|
||||
{:else}
|
||||
<IconButton shape="round" color="secondary" variant="ghost" aria-label={text} {icon} onclick={handleArchive} />
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
+2
-6
@@ -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 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||
{/if}
|
||||
{#if assetMultiSelectManager.assets.length === 1}
|
||||
|
||||
@@ -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 @@
|
||||
<AssetSelectControlBar>
|
||||
{const Actions = $derived(getAssetBulkActions($t))}
|
||||
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
|
||||
<ArchiveAction
|
||||
unarchive
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionButton action={Actions.Unarchive} />
|
||||
<ActionButton action={Actions.CreateSharedLink} />
|
||||
<SelectAllAssets {timelineManager} assetInteraction={assetMultiSelectManager} />
|
||||
<ActionButton action={Actions.AddToAlbum} />
|
||||
|
||||
@@ -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 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||
<DeleteAssets
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import TreeItems from '#lib/components/shared-components/tree/TreeItems.svelte';
|
||||
import Sidebar from '#lib/components/sidebar/Sidebar.svelte';
|
||||
import AssetSelectControlBar from '#lib/components/timeline/AssetSelectControlBar.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';
|
||||
@@ -111,7 +110,7 @@
|
||||
</Sidebar>
|
||||
{/snippet}
|
||||
|
||||
<OnEvents onAssetsDelete={refreshAll} />
|
||||
<OnEvents onAssetsDelete={refreshAll} onAssetsArchive={triggerAssetUpdate} onAssetsUnarchive={triggerAssetUpdate} />
|
||||
|
||||
<TreeBreadcrumbs node={data.tree} icon={mdiFolderHome} title={$t('folders')} getLink={getLinkForPath} />
|
||||
|
||||
@@ -168,7 +167,8 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction menuItem unarchive={assetMultiSelectManager.isAllArchived} onArchive={triggerAssetUpdate} />
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets menuItem onAssetDelete={triggerAssetUpdate} onUndoDelete={triggerAssetUpdate} />
|
||||
|
||||
@@ -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 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets
|
||||
menuItem
|
||||
|
||||
+4
-2
@@ -4,10 +4,10 @@
|
||||
import { shortcuts } from '#lib/actions/shortcut.ts';
|
||||
import ActionMenuItem from '#lib/components/ActionMenuItem.svelte';
|
||||
import BirthdayConfetti from '#lib/components/memories/BirthdayConfetti.svelte';
|
||||
import OnEvents from '#lib/components/OnEvents.svelte';
|
||||
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
|
||||
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
|
||||
import GalleryViewer from '#lib/components/shared-components/gallery-viewer/GalleryViewer.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';
|
||||
@@ -274,6 +274,8 @@
|
||||
]}
|
||||
/>
|
||||
|
||||
<OnEvents onAssetsArchive={handleHideAssets} />
|
||||
|
||||
{#if assetMultiSelectManager.selectionActive}
|
||||
<div class="dark sticky top-0 z-1">
|
||||
<AssetSelectControlBar>
|
||||
@@ -299,7 +301,7 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction menuItem unarchive={assetMultiSelectManager.isAllArchived} onArchive={handleHideAssets} />
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets menuItem onAssetDelete={handleHideAssets} />
|
||||
</ButtonContextMenu>
|
||||
|
||||
+2
-9
@@ -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 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={(ids, visibility) =>
|
||||
timelineManager.update(ids, (asset) => {
|
||||
asset.visibility = visibility;
|
||||
})}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||
<DeleteAssets
|
||||
|
||||
@@ -152,10 +152,8 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets
|
||||
menuItem
|
||||
|
||||
@@ -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';
|
||||
@@ -127,10 +126,8 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets
|
||||
menuItem
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import ControlAppBar from '#lib/components/shared-components/ControlAppBar.svelte';
|
||||
import GalleryViewer from '#lib/components/shared-components/gallery-viewer/GalleryViewer.svelte';
|
||||
import SearchBar from '#lib/components/shared-components/search-bar/SearchBar.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';
|
||||
@@ -19,7 +18,7 @@
|
||||
import { QueryParameter } from '#lib/constants.ts';
|
||||
import { assetMultiSelectManager } from '#lib/managers/asset-multi-select-manager.svelte.ts';
|
||||
import { searchManager } from '#lib/managers/search-manager.svelte.ts';
|
||||
import type { Viewport } from '#lib/managers/timeline-manager/types.ts';
|
||||
import type { TimelineAsset, Viewport } from '#lib/managers/timeline-manager/types.ts';
|
||||
import { Route } from '#lib/route.ts';
|
||||
import { getAssetBulkActions } from '#lib/services/asset.service.ts';
|
||||
import { lang, locale } from '#lib/stores/preferences.store.ts';
|
||||
@@ -239,6 +238,21 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onAssetsArchive = (assetIds: string[]) => {
|
||||
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<T extends object>(obj: T): (keyof T)[] {
|
||||
return Object.keys(obj) as (keyof T)[];
|
||||
}
|
||||
@@ -254,7 +268,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY />
|
||||
<OnEvents {onAlbumAddAssets} />
|
||||
<OnEvents {onAlbumAddAssets} {onAssetsArchive} {onAssetsUnarchive} />
|
||||
|
||||
{#if searchTermKeys.length > 0}
|
||||
<section id="search-chips" class="mx-auto mt-24 w-full max-w-7xl px-4 sm:px-8 lg:px-12">
|
||||
@@ -377,7 +391,8 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction menuItem unarchive={assetMultiSelectManager.isAllArchived} />
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
<ChangeDate menuItem />
|
||||
<ChangeDescription menuItem />
|
||||
<ChangeLocation menuItem />
|
||||
<ArchiveAction
|
||||
menuItem
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
<ActionMenuItem action={Actions.Archive} />
|
||||
<ActionMenuItem action={Actions.Unarchive} />
|
||||
<ActionMenuItem action={Actions.Tag} />
|
||||
<DeleteAssets
|
||||
menuItem
|
||||
|
||||
Reference in New Issue
Block a user