refactor: asset select manager (#27330)

This commit is contained in:
Jason Rasmussen
2026-03-30 10:45:57 -04:00
committed by GitHub
parent b09ebb11e9
commit 17d4941089
30 changed files with 77 additions and 112 deletions
@@ -337,7 +337,7 @@
{#if assetMultiSelectManager.selectionActive}
<div class="sticky top-0 z-1 dark">
<AssetSelectControlBar forceDark>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CreateSharedLink />
<IconButton
shape="round"
@@ -118,7 +118,7 @@
</aside>
{#if assetMultiSelectManager.selectionActive}
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<Portal target="body">
@@ -1,7 +1,6 @@
<script lang="ts">
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { setAssetControlContext } from '$lib/utils/context';
import { mdiClose } from '@mdi/js';
import type { Snippet } from 'svelte';
import { t } from 'svelte-i18n';
@@ -13,8 +12,6 @@
let { children, forceDark }: Props = $props();
setAssetControlContext(assetMultiSelectManager.asControlContext());
const onClose = () => assetMultiSelectManager.clear();
const assets = $derived(assetMultiSelectManager.assets);
@@ -1,18 +1,18 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import type { OnArchive } from '$lib/utils/actions';
import { archiveAssets } from '$lib/utils/asset-utils';
import { getAssetControlContext } from '$lib/utils/context';
import { AssetVisibility } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { mdiArchiveArrowDownOutline, mdiArchiveArrowUpOutline, mdiTimerSand } from '@mdi/js';
import { t } from 'svelte-i18n';
interface Props {
type Props = {
onArchive?: OnArchive;
menuItem?: boolean;
unarchive?: boolean;
}
};
let { onArchive, menuItem = false, unarchive = false }: Props = $props();
@@ -21,16 +21,14 @@
let loading = $state(false);
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleArchive = async () => {
const visibility = unarchive ? AssetVisibility.Timeline : AssetVisibility.Archive;
const assets = [...getOwnedAssets()].filter((asset) => asset.visibility !== visibility);
const assets = assetMultiSelectManager.getOwnedAssets().filter((asset) => asset.visibility !== visibility);
loading = true;
const ids = await archiveAssets(assets, visibility as AssetVisibility);
if (ids) {
onArchive?.(ids, visibility);
clearSelect();
assetMultiSelectManager.clear();
}
loading = false;
};
@@ -1,28 +1,28 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import AssetSelectionChangeDateModal from '$lib/modals/AssetSelectionChangeDateModal.svelte';
import { getAssetControlContext } from '$lib/utils/context';
import { fromTimelinePlainDateTime } from '$lib/utils/timeline-util';
import { modalManager } from '@immich/ui';
import { mdiCalendarEditOutline } from '@mdi/js';
import { DateTime } from 'luxon';
import { t } from 'svelte-i18n';
interface Props {
type Props = {
menuItem?: boolean;
}
};
let { menuItem = false }: Props = $props();
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleChangeDate = async () => {
const assets = getOwnedAssets();
const assets = assetMultiSelectManager.ownedAssets;
const initialDate = assets.length === 1 ? fromTimelinePlainDateTime(assets[0].localDateTime) : DateTime.now();
const success = await modalManager.show(AssetSelectionChangeDateModal, {
initialDate,
assets,
});
if (success) {
clearSelect();
assetMultiSelectManager.clear();
}
};
</script>
@@ -1,8 +1,8 @@
<script lang="ts">
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import AssetUpdateDescriptionConfirmModal from '$lib/modals/AssetUpdateDescriptionConfirmModal.svelte';
import { user } from '$lib/stores/user.store';
import { getOwnedAssetsWithWarning } from '$lib/utils/asset-utils';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { updateAssets } from '@immich/sdk';
import { modalManager } from '@immich/ui';
@@ -15,19 +15,18 @@
}
let { menuItem = false }: Props = $props();
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleUpdateDescription = async () => {
const description = await modalManager.show(AssetUpdateDescriptionConfirmModal);
if (description) {
const ids = getOwnedAssetsWithWarning(getOwnedAssets(), $user);
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, $user);
try {
await updateAssets({ assetBulkUpdateDto: { ids, description } });
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_change_description'));
}
clearSelect();
}
};
</script>
@@ -1,9 +1,9 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import GeolocationPointPickerModal from '$lib/modals/GeolocationPointPickerModal.svelte';
import { user } from '$lib/stores/user.store';
import { getOwnedAssetsWithWarning } from '$lib/utils/asset-utils';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { updateAssets } from '@immich/sdk';
import { modalManager, toastManager } from '@immich/ui';
@@ -15,7 +15,6 @@
};
let { menuItem = false }: Props = $props();
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const onAction = async () => {
const point = await modalManager.show(GeolocationPointPickerModal, {});
@@ -23,12 +22,12 @@
return;
}
const ids = getOwnedAssetsWithWarning(getOwnedAssets(), $user);
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, $user);
try {
await updateAssets({ assetBulkUpdateDto: { ids, latitude: point.lat, longitude: point.lng } });
toastManager.primary();
clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_update_location'));
}
@@ -1,14 +1,12 @@
<script lang="ts">
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { getAssetControlContext } from '$lib/utils/context';
import { IconButton, modalManager } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
const { getAssets } = getAssetControlContext();
const handleClick = async () => {
await modalManager.show(SharedLinkCreateModal, { assetIds: [...getAssets()].map(({ id }) => id) });
await modalManager.show(SharedLinkCreateModal, { assetIds: assetMultiSelectManager.assets.map(({ id }) => id) });
};
</script>
@@ -1,10 +1,10 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
import { showDeleteModal } from '$lib/stores/preferences.store';
import { type OnDelete, type OnUndoDelete, deleteAssets } from '$lib/utils/actions';
import { getAssetControlContext } from '$lib/utils/context';
import { IconButton, modalManager } from '@immich/ui';
import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -22,10 +22,8 @@
let label = $derived(force ? $t('permanently_delete') : $t('delete'));
let loading = $state(false);
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const onAction = async () => {
const assets = getOwnedAssets();
const assets = assetMultiSelectManager.ownedAssets;
if (force && $showDeleteModal) {
const confirmed = await modalManager.show(AssetDeleteConfirmModal, { size: assets.length });
@@ -36,7 +34,7 @@
loading = true;
await deleteAssets(force, onAssetDelete, assets, onUndoDelete);
clearSelect();
assetMultiSelectManager.clear();
loading = false;
};
</script>
@@ -1,15 +1,15 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { handleDownloadAsset } from '$lib/services/asset.service';
import { downloadArchive } from '$lib/utils/asset-utils';
import { getAssetControlContext } from '$lib/utils/context';
import { getAssetInfo } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { mdiDownload } from '@mdi/js';
import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
interface Props {
filename?: string;
@@ -18,18 +18,16 @@
let { filename = 'immich.zip', menuItem = false }: Props = $props();
const { getAssets, clearSelect } = getAssetControlContext();
const handleDownloadFiles = async () => {
const assets = [...getAssets()];
const assets = assetMultiSelectManager.assets;
if (assets.length === 1) {
clearSelect();
assetMultiSelectManager.clear();
let asset = await getAssetInfo({ ...authManager.params, id: assets[0].id });
await handleDownloadAsset(asset, { edited: true });
return;
}
clearSelect();
assetMultiSelectManager.clear();
await downloadArchive(filename, { assetIds: assets.map((asset) => asset.id) });
};
</script>
@@ -1,7 +1,7 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import type { OnFavorite } from '$lib/utils/actions';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { updateAssets } from '@immich/sdk';
import { IconButton, toastManager } from '@immich/ui';
@@ -21,14 +21,12 @@
let loading = $state(false);
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleFavorite = async () => {
const isFavorite = !removeFavorite;
loading = true;
try {
const assets = [...getOwnedAssets()].filter((asset) => asset.isFavorite !== isFavorite);
const assets = assetMultiSelectManager.ownedAssets.filter((asset) => asset.isFavorite !== isFavorite);
const ids = assets.map(({ id }) => id);
@@ -48,7 +46,7 @@
: $t('removed_from_favorites_count', { values: { count: ids.length } }),
);
clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_add_remove_favorites', { values: { favorite: isFavorite } }));
} finally {
@@ -1,15 +1,15 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import type { OnLink, OnUnlink } from '$lib/utils/actions';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { getAssetInfo, updateAsset } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { mdiLinkOff, mdiMotionPlayOutline, mdiTimerSand } from '@mdi/js';
import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
interface Props {
onLink: OnLink;
@@ -25,12 +25,10 @@
let text = $derived(unlink ? $t('unlink_motion_video') : $t('link_motion_video'));
let icon = $derived(unlink ? mdiLinkOff : mdiMotionPlayOutline);
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const onClick = () => (unlink ? handleUnlink() : handleLink());
const handleLink = async () => {
let [still, motion] = [...getOwnedAssets()];
let [still, motion] = assetMultiSelectManager.ownedAssets;
if ((still as TimelineAsset).isVideo) {
[still, motion] = [motion, still];
}
@@ -39,7 +37,7 @@
loading = true;
const stillResponse = await updateAsset({ id: still.id, updateAssetDto: { livePhotoVideoId: motion.id } });
onLink({ still: toTimelineAsset(stillResponse), motion: motion as TimelineAsset });
clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_link_motion_video'));
} finally {
@@ -48,7 +46,7 @@
};
const handleUnlink = async () => {
const [still] = [...getOwnedAssets()];
const [still] = assetMultiSelectManager.ownedAssets;
if (!still) {
return;
}
@@ -61,7 +59,7 @@
const stillResponse = await updateAsset({ id: still.id, updateAssetDto: { livePhotoVideoId: null } });
const motionResponse = await getAssetInfo({ ...authManager.params, id: motionId });
onUnlink({ still: toTimelineAsset(stillResponse), motion: toTimelineAsset(motionResponse) });
clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_unlink_motion_video'));
} finally {
@@ -1,11 +1,11 @@
<script lang="ts">
import { getAssetControlContext } from '$lib/utils/context';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { handleError } from '$lib/utils/handle-error';
import { getAlbumInfo, removeAssetFromAlbum, type AlbumResponseDto } from '@immich/sdk';
import { IconButton, modalManager, toastManager } from '@immich/ui';
import { mdiDeleteOutline, mdiImageRemoveOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
interface Props {
album: AlbumResponseDto;
@@ -16,10 +16,8 @@
let { album = $bindable(), onRemove, assetIds, menuItem = false }: Props = $props();
const context = getAssetControlContext();
const removeFromAlbum = async () => {
const ids = assetIds ?? context?.getAssets().map(({ id }) => id) ?? [];
const ids = assetIds ?? assetMultiSelectManager.assets.map(({ id }) => id) ?? [];
const isConfirmed = await modalManager.showDialog({
prompt: $t('remove_assets_album_confirmation', { values: { count: ids.length } }),
@@ -42,7 +40,7 @@
const count = results.filter(({ success }) => success).length;
toastManager.primary($t('assets_removed_count', { values: { count } }));
context?.clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.error_removing_assets_from_album'));
}
@@ -1,7 +1,7 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { handleRemoveSharedLinkAssets } from '$lib/services/shared-link.service';
import { getAssetControlContext } from '$lib/utils/context';
import { type SharedLinkResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui';
import { mdiDeleteOutline } from '@mdi/js';
@@ -13,13 +13,11 @@
let { sharedLink = $bindable() }: Props = $props();
const { getAssets, clearSelect } = getAssetControlContext();
const handleSelect = async () => {
const assetIds = getAssets().map(({ id }) => id);
const assetIds = assetMultiSelectManager.assets.map(({ id }) => id);
const success = await handleRemoveSharedLinkAssets(sharedLink, assetIds);
if (success) {
clearSelect();
assetMultiSelectManager.clear();
}
};
</script>
@@ -1,6 +1,6 @@
<script lang="ts">
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import type { OnRestore } from '$lib/utils/actions';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { restoreAssets } from '@immich/sdk';
import { Button, toastManager } from '@immich/ui';
@@ -13,19 +13,17 @@
let { onRestore }: Props = $props();
const { getAssets, clearSelect } = getAssetControlContext();
let loading = $state(false);
const handleRestore = async () => {
loading = true;
try {
const ids = [...getAssets()].map((a) => a.id);
const ids = assetMultiSelectManager.assets.map((a) => a.id);
await restoreAssets({ bulkIdsDto: { ids } });
onRestore?.(ids);
toastManager.primary($t('assets_restored_count', { values: { count: ids.length } }));
clearSelect();
assetMultiSelectManager.clear();
} catch (error) {
handleError(error, $t('errors.unable_to_restore_assets'));
} finally {
@@ -1,7 +1,7 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import type { OnSetVisibility } from '$lib/utils/actions';
import { getAssetControlContext } from '$lib/utils/context';
import { handleError } from '$lib/utils/handle-error';
import { AssetVisibility, updateAssets } from '@immich/sdk';
import { Button, modalManager } from '@immich/ui';
@@ -16,7 +16,6 @@
let { onVisibilitySet, menuItem = false, unlock = false }: Props = $props();
let loading = $state(false);
const { getAssets } = getAssetControlContext();
const setLockedVisibility = async () => {
const isConfirmed = await modalManager.showDialog({
@@ -33,7 +32,7 @@
try {
loading = true;
const assetIds = getAssets().map(({ id }) => id);
const assetIds = assetMultiSelectManager.assets.map(({ id }) => id);
await updateAssets({
assetBulkUpdateDto: {
@@ -1,8 +1,8 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import type { OnStack, OnUnstack } from '$lib/utils/actions';
import { deleteStack, stackAssets } from '$lib/utils/asset-utils';
import { getAssetControlContext } from '$lib/utils/context';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { mdiImageMultipleOutline, mdiImageOffOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -15,17 +15,14 @@
let { unstack = false, onStack, onUnstack }: Props = $props();
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleStack = async () => {
const selectedAssets = [...getOwnedAssets()];
const result = await stackAssets(selectedAssets);
const result = await stackAssets(assetMultiSelectManager.ownedAssets);
onStack?.(result);
clearSelect();
assetMultiSelectManager.clear();
};
const handleUnstack = async () => {
const selectedAssets = [...getOwnedAssets()];
const selectedAssets = assetMultiSelectManager.ownedAssets;
if (selectedAssets.length !== 1) {
return;
}
@@ -37,7 +34,7 @@
if (unstackedAssets) {
onUnstack?.(unstackedAssets.map((a) => toTimelineAsset(a)));
}
clearSelect();
assetMultiSelectManager.clear();
};
</script>
@@ -1,11 +1,11 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
import { getAssetControlContext } from '$lib/utils/context';
import { IconButton, modalManager } from '@immich/ui';
import { mdiTagMultipleOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
interface Props {
menuItem?: boolean;
@@ -16,13 +16,11 @@
const text = $t('tag');
const icon = mdiTagMultipleOutline;
const { clearSelect, getOwnedAssets } = getAssetControlContext();
const handleTagAssets = async () => {
const assets = [...getOwnedAssets()];
const assets = assetMultiSelectManager.ownedAssets;
const didUpdate = await modalManager.show(AssetTagModal, { assetIds: assets.map(({ id }) => id) });
if (didUpdate) {
clearSelect();
assetMultiSelectManager.clear();
}
};
</script>
@@ -1,7 +1,6 @@
import { eventManager } from '$lib/managers/event-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { user } from '$lib/stores/user.store';
import type { AssetControlContext } from '$lib/types';
import { AssetVisibility, type UserAdminResponseDto } from '@immich/sdk';
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
import { fromStore } from 'svelte/store';
@@ -22,7 +21,10 @@ export class AssetMultiSelectManager {
candidates = $state<TimelineAsset[]>([]);
selectionActive = $derived(this.#selectedMap.size > 0);
assets = $derived(Array.from(this.#selectedMap.values()));
ownedAssets = $derived(this.#userId ? this.assets.filter((asset) => asset.ownerId === this.#userId) : this.assets);
isAllTrashed = $derived(this.assets.every((asset) => asset.isTrashed));
isAllArchived = $derived(this.assets.every((asset) => asset.visibility === AssetVisibility.Archive));
isAllFavorite = $derived(this.assets.every((asset) => asset.isFavorite));
@@ -41,13 +43,8 @@ export class AssetMultiSelectManager {
this.#unsubscribe?.();
}
asControlContext(): AssetControlContext {
return {
getOwnedAssets: () =>
this.#userId ? this.assets.filter((asset) => asset.ownerId === this.#userId) : this.assets,
getAssets: () => this.assets,
clearSelect: () => this.clear(),
};
getOwnedAssets() {
return this.#userId ? this.assets.filter((asset) => asset.ownerId === this.#userId) : this.assets;
}
hasSelectedAsset(assetId: string) {
+4 -4
View File
@@ -1,4 +1,5 @@
import { ProjectionType } from '$lib/constants';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
@@ -6,7 +7,6 @@ import AssetAddToAlbumModal from '$lib/modals/AssetAddToAlbumModal.svelte';
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { user as authUser, preferences } from '$lib/stores/user.store';
import type { AssetControlContext } from '$lib/types';
import { getAssetMediaUrl, getSharedLink, sleep } from '$lib/utils';
import { downloadUrl } from '$lib/utils/asset-utils';
import { handleError } from '$lib/utils/handle-error';
@@ -48,14 +48,14 @@ import {
import type { MessageFormatter } from 'svelte-i18n';
import { get } from 'svelte/store';
export const getAssetBulkActions = ($t: MessageFormatter, ctx: AssetControlContext) => {
const ownedAssets = ctx.getOwnedAssets();
export const getAssetBulkActions = ($t: MessageFormatter) => {
const ownedAssets = assetMultiSelectManager.ownedAssets;
const assetIds = ownedAssets.map((asset) => asset.id);
const isAllVideos = ownedAssets.every((asset) => asset.isVideo);
const onAction = async (name: AssetJobName) => {
await handleRunAssetJob({ name, assetIds });
ctx.clearSelect();
assetMultiSelectManager.clear();
};
const AddToAlbum: ActionItem = {
-3
View File
@@ -1,4 +1,3 @@
import type { AssetControlContext } from '$lib/types';
import { getContext, setContext } from 'svelte';
export function createContext<T>(key: string | symbol = Symbol()) {
@@ -7,5 +6,3 @@ export function createContext<T>(key: string | symbol = Symbol()) {
set: (context: T) => setContext<T>(key, context),
};
}
export const { get: getAssetControlContext, set: setAssetControlContext } = createContext<AssetControlContext>();
@@ -452,7 +452,7 @@
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
<SelectAllAssets {timelineManager} assetInteraction={assetMultiSelectManager} />
@@ -60,7 +60,7 @@
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<ArchiveAction
unarchive
@@ -64,7 +64,7 @@
<!-- Multiselection mode app bar -->
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<FavoriteAction removeFavorite onFavorite={(assetIds) => timelineManager.removeAssets(assetIds)} />
<CreateSharedLink />
@@ -111,7 +111,7 @@
{#if assetMultiSelectManager.selectionActive}
<div class="fixed top-0 start-0 w-full">
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
<IconButton
@@ -40,7 +40,7 @@
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
<ActionButton action={Actions.AddToAlbum} />
@@ -459,7 +459,7 @@
<header>
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
<SelectAllAssets {timelineManager} assetInteraction={assetMultiSelectManager} />
@@ -113,7 +113,7 @@
{#if assetMultiSelectManager.selectionActive}
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
@@ -319,7 +319,7 @@
{#if assetMultiSelectManager.selectionActive}
<div class="fixed top-0 start-0 w-full z-2">
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
@@ -114,7 +114,7 @@
{#if assetMultiSelectManager.selectionActive}
<div class="fixed top-0 start-0 w-full">
<AssetSelectControlBar>
{@const Actions = getAssetBulkActions($t, assetMultiSelectManager.asControlContext())}
{@const Actions = getAssetBulkActions($t)}
<CommandPaletteDefaultProvider name={$t('assets')} actions={Object.values(Actions)} />
<CreateSharedLink />
<SelectAllAssets {timelineManager} assetInteraction={assetMultiSelectManager} />