mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: commands (#27546)
This commit is contained in:
@@ -90,7 +90,6 @@
|
||||
|
||||
const Close: ActionItem = $derived({
|
||||
title: $t('go_back'),
|
||||
type: $t('assets'),
|
||||
icon: languageManager.rtl ? mdiArrowRight : mdiArrowLeft,
|
||||
$if: () => !!onClose && !assetViewerManager.isFaceEditMode,
|
||||
onAction: () => onClose?.(),
|
||||
|
||||
@@ -46,7 +46,6 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
|
||||
|
||||
const Share: ActionItem = {
|
||||
title: $t('share'),
|
||||
type: $t('command'),
|
||||
icon: mdiShareVariantOutline,
|
||||
$if: () => isOwned,
|
||||
onAction: () => modalManager.show(AlbumOptionsModal, { album }),
|
||||
@@ -54,7 +53,6 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
|
||||
|
||||
const AddUsers: ActionItem = {
|
||||
title: $t('invite_people'),
|
||||
type: $t('command'),
|
||||
icon: mdiPlus,
|
||||
color: 'primary',
|
||||
onAction: () => modalManager.show(AlbumAddUsersModal, { album }),
|
||||
@@ -62,7 +60,6 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
|
||||
|
||||
const CreateSharedLink: ActionItem = {
|
||||
title: $t('create_link'),
|
||||
type: $t('command'),
|
||||
icon: mdiLink,
|
||||
color: 'primary',
|
||||
onAction: () => modalManager.show(SharedLinkCreateModal, { albumId: album.id }),
|
||||
@@ -74,7 +71,6 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
|
||||
export const getAlbumAssetsActions = ($t: MessageFormatter, album: AlbumResponseDto, assets: TimelineAsset[]) => {
|
||||
const AddAssets: ActionItem = {
|
||||
title: $t('add_assets'),
|
||||
type: $t('command'),
|
||||
color: 'primary',
|
||||
icon: mdiPlusBoxOutline,
|
||||
$if: () => assets.length > 0,
|
||||
@@ -89,7 +85,6 @@ export const getAlbumAssetsActions = ($t: MessageFormatter, album: AlbumResponse
|
||||
const Upload: ActionItem = {
|
||||
title: $t('select_from_computer'),
|
||||
description: $t('album_upload_assets'),
|
||||
type: $t('command'),
|
||||
icon: mdiUpload,
|
||||
onAction: () => void openFileUploadDialog({ albumId: album.id }),
|
||||
};
|
||||
|
||||
@@ -129,7 +129,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const PlayMotionPhoto: ActionItem = {
|
||||
title: $t('play_motion_photo'),
|
||||
icon: mdiMotionPlayOutline,
|
||||
type: $t('assets'),
|
||||
$if: () => !!asset.livePhotoVideoId && !assetViewerManager.isPlayingMotionPhoto,
|
||||
onAction: () => {
|
||||
assetViewerManager.isPlayingMotionPhoto = true;
|
||||
@@ -139,7 +138,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const StopMotionPhoto: ActionItem = {
|
||||
title: $t('stop_motion_photo'),
|
||||
icon: mdiMotionPauseOutline,
|
||||
type: $t('assets'),
|
||||
$if: () => !!asset.livePhotoVideoId && assetViewerManager.isPlayingMotionPhoto,
|
||||
onAction: () => {
|
||||
assetViewerManager.isPlayingMotionPhoto = false;
|
||||
@@ -149,7 +147,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const Favorite: ActionItem = {
|
||||
title: $t('to_favorite'),
|
||||
icon: mdiHeartOutline,
|
||||
type: $t('assets'),
|
||||
$if: () => isOwner && !asset.isFavorite,
|
||||
onAction: () => handleFavorite(asset),
|
||||
shortcuts: [{ key: 'f' }],
|
||||
@@ -158,7 +155,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const Unfavorite: ActionItem = {
|
||||
title: $t('unfavorite'),
|
||||
icon: mdiHeart,
|
||||
type: $t('assets'),
|
||||
$if: () => isOwner && asset.isFavorite,
|
||||
onAction: () => handleUnfavorite(asset),
|
||||
shortcuts: [{ key: 'f' }],
|
||||
@@ -175,7 +171,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const Offline: ActionItem = {
|
||||
title: $t('asset_offline'),
|
||||
icon: mdiAlertOutline,
|
||||
type: $t('assets'),
|
||||
color: 'danger',
|
||||
$if: () => !!asset.isOffline,
|
||||
onAction: () => assetViewerManager.toggleDetailPanel(),
|
||||
@@ -205,7 +200,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const Info: ActionItem = {
|
||||
title: $t('info'),
|
||||
icon: mdiInformationOutline,
|
||||
type: $t('assets'),
|
||||
$if: () => asset.hasMetadata,
|
||||
onAction: () => assetViewerManager.toggleDetailPanel(),
|
||||
shortcuts: { key: 'i' },
|
||||
@@ -223,7 +217,6 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
|
||||
const TagPeople: ActionItem = {
|
||||
title: $t('tag_people'),
|
||||
icon: mdiFaceRecognition,
|
||||
type: $t('assets'),
|
||||
$if: () => isOwner && asset.type === AssetTypeEnum.Image && !asset.isTrashed,
|
||||
onAction: () => assetViewerManager.toggleFaceEditMode(),
|
||||
shortcuts: { key: 'p' },
|
||||
|
||||
@@ -16,14 +16,12 @@ import type { MessageFormatter } from 'svelte-i18n';
|
||||
|
||||
export const getDatabaseBackupActions = ($t: MessageFormatter, filename: string) => {
|
||||
const Download: ActionItem = {
|
||||
type: $t('command'),
|
||||
title: $t('download'),
|
||||
icon: mdiDownload,
|
||||
onAction: () => handleDownloadDatabaseBackup(filename),
|
||||
};
|
||||
|
||||
const Delete: ActionItem = {
|
||||
type: $t('command'),
|
||||
title: $t('delete'),
|
||||
icon: mdiTrashCanOutline,
|
||||
color: 'danger',
|
||||
|
||||
@@ -26,7 +26,6 @@ import type { MessageFormatter } from 'svelte-i18n';
|
||||
export const getLibrariesActions = ($t: MessageFormatter) => {
|
||||
const ScanAll: ActionItem = {
|
||||
title: $t('scan_all_libraries'),
|
||||
type: $t('command'),
|
||||
icon: mdiSync,
|
||||
onAction: () => handleScanAllLibraries(),
|
||||
shortcuts: { shift: true, key: 'r' },
|
||||
@@ -34,7 +33,6 @@ export const getLibrariesActions = ($t: MessageFormatter) => {
|
||||
|
||||
const Create: ActionItem = {
|
||||
title: $t('create_library'),
|
||||
type: $t('command'),
|
||||
icon: mdiPlusBoxOutline,
|
||||
onAction: () => goto(Route.newLibrary()),
|
||||
shortcuts: { shift: true, key: 'n' },
|
||||
@@ -46,14 +44,12 @@ export const getLibrariesActions = ($t: MessageFormatter) => {
|
||||
export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponseDto) => {
|
||||
const Detail: ActionItem = {
|
||||
icon: mdiInformationOutline,
|
||||
type: $t('command'),
|
||||
title: $t('details'),
|
||||
onAction: () => goto(Route.viewLibrary(library)),
|
||||
};
|
||||
|
||||
const Edit: ActionItem = {
|
||||
icon: mdiPencilOutline,
|
||||
type: $t('command'),
|
||||
title: $t('edit'),
|
||||
onAction: () => goto(Route.editLibrary(library)),
|
||||
shortcuts: { key: 'r' },
|
||||
@@ -61,7 +57,6 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse
|
||||
|
||||
const Delete: ActionItem = {
|
||||
icon: mdiTrashCanOutline,
|
||||
type: $t('command'),
|
||||
title: $t('delete'),
|
||||
color: 'danger',
|
||||
onAction: () => handleDeleteLibrary(library),
|
||||
@@ -71,21 +66,18 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse
|
||||
|
||||
const AddFolder: ActionItem = {
|
||||
icon: mdiPlusBoxOutline,
|
||||
type: $t('command'),
|
||||
title: $t('add'),
|
||||
onAction: () => modalManager.show(LibraryFolderAddModal, { library }),
|
||||
};
|
||||
|
||||
const AddExclusionPattern: ActionItem = {
|
||||
icon: mdiPlusBoxOutline,
|
||||
type: $t('command'),
|
||||
title: $t('add'),
|
||||
onAction: () => modalManager.show(LibraryExclusionPatternAddModal, { library }),
|
||||
};
|
||||
|
||||
const Scan: ActionItem = {
|
||||
icon: mdiSync,
|
||||
type: $t('command'),
|
||||
title: $t('scan_library'),
|
||||
onAction: () => handleScanLibrary(library),
|
||||
shortcuts: { shift: true, key: 'r' },
|
||||
@@ -97,14 +89,12 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse
|
||||
export const getLibraryFolderActions = ($t: MessageFormatter, library: LibraryResponseDto, folder: string) => {
|
||||
const Edit: ActionItem = {
|
||||
icon: mdiPencilOutline,
|
||||
type: $t('command'),
|
||||
title: $t('edit'),
|
||||
onAction: () => modalManager.show(LibraryFolderEditModal, { folder, library }),
|
||||
};
|
||||
|
||||
const Delete: ActionItem = {
|
||||
icon: mdiTrashCanOutline,
|
||||
type: $t('command'),
|
||||
title: $t('delete'),
|
||||
onAction: () => handleDeleteLibraryFolder(library, folder),
|
||||
};
|
||||
@@ -119,14 +109,12 @@ export const getLibraryExclusionPatternActions = (
|
||||
) => {
|
||||
const Edit: ActionItem = {
|
||||
icon: mdiPencilOutline,
|
||||
type: $t('command'),
|
||||
title: $t('edit'),
|
||||
onAction: () => modalManager.show(LibraryExclusionPatternEditModal, { exclusionPattern, library }),
|
||||
};
|
||||
|
||||
const Delete: ActionItem = {
|
||||
icon: mdiTrashCanOutline,
|
||||
type: $t('command'),
|
||||
title: $t('delete'),
|
||||
onAction: () => handleDeleteExclusionPattern(library, exclusionPattern),
|
||||
};
|
||||
|
||||
@@ -64,7 +64,6 @@ export const getQueuesActions = ($t: MessageFormatter, queues: QueueResponseDto[
|
||||
const CreateJob: ActionItem = {
|
||||
icon: mdiPlus,
|
||||
title: $t('admin.create_job'),
|
||||
type: $t('command'),
|
||||
shortcuts: { shift: true, key: 'n' },
|
||||
onAction: () => modalManager.show(JobCreateModal, {}),
|
||||
};
|
||||
@@ -73,7 +72,6 @@ export const getQueuesActions = ($t: MessageFormatter, queues: QueueResponseDto[
|
||||
icon: mdiCog,
|
||||
title: $t('admin.manage_concurrency'),
|
||||
description: $t('admin.manage_concurrency_description'),
|
||||
type: $t('page'),
|
||||
onAction: () => goto(Route.systemSettings({ isOpen: OpenQueryParam.JOB })),
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ export const getSystemConfigActions = (
|
||||
const CopyToClipboard: ActionItem = {
|
||||
title: $t('copy_to_clipboard'),
|
||||
description: $t('admin.copy_config_to_clipboard_description'),
|
||||
type: $t('command'),
|
||||
icon: mdiContentCopy,
|
||||
onAction: () => handleCopyToClipboard(config),
|
||||
shortcuts: { shift: true, key: 'c' },
|
||||
@@ -27,7 +26,6 @@ export const getSystemConfigActions = (
|
||||
const Download: ActionItem = {
|
||||
title: $t('export_as_json'),
|
||||
description: $t('admin.export_config_as_json_description'),
|
||||
type: $t('command'),
|
||||
icon: mdiDownload,
|
||||
onAction: () => handleDownloadConfig(config),
|
||||
shortcuts: [
|
||||
@@ -39,7 +37,6 @@ export const getSystemConfigActions = (
|
||||
const Upload: ActionItem = {
|
||||
title: $t('import_from_json'),
|
||||
description: $t('admin.import_config_from_json_description'),
|
||||
type: $t('command'),
|
||||
icon: mdiUpload,
|
||||
$if: () => !featureFlags.configFile,
|
||||
onAction: () => handleUploadConfig(),
|
||||
|
||||
@@ -36,7 +36,6 @@ import type { MessageFormatter } from 'svelte-i18n';
|
||||
export const getUserAdminsActions = ($t: MessageFormatter) => {
|
||||
const Create: ActionItem = {
|
||||
title: $t('create_user'),
|
||||
type: $t('command'),
|
||||
icon: mdiPlusBoxOutline,
|
||||
onAction: () => goto(Route.newUser()),
|
||||
shortcuts: { shift: true, key: 'n' },
|
||||
@@ -61,7 +60,6 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons
|
||||
const Delete: ActionItem = {
|
||||
icon: mdiTrashCanOutline,
|
||||
title: $t('delete'),
|
||||
type: $t('command'),
|
||||
color: 'danger',
|
||||
$if: () => authManager.user.id !== user.id && !user.deletedAt,
|
||||
onAction: () => modalManager.show(UserDeleteConfirmModal, { user }),
|
||||
@@ -75,7 +73,6 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons
|
||||
const Restore: HeaderButtonActionItem = {
|
||||
icon: mdiDeleteRestore,
|
||||
title: $t('restore'),
|
||||
type: $t('command'),
|
||||
color: 'primary',
|
||||
data: {
|
||||
title: $t('admin.user_restore_scheduled_removal', { values: { date: getDeleteDate(user.deletedAt!) } }),
|
||||
@@ -87,14 +84,12 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons
|
||||
const ResetPassword: ActionItem = {
|
||||
icon: mdiLockReset,
|
||||
title: $t('reset_password'),
|
||||
type: $t('command'),
|
||||
$if: () => authManager.user.id !== user.id,
|
||||
onAction: () => handleResetPasswordUserAdmin(user),
|
||||
};
|
||||
|
||||
const ResetPinCode: ActionItem = {
|
||||
icon: mdiLockSmart,
|
||||
type: $t('command'),
|
||||
title: $t('reset_pin_code'),
|
||||
onAction: () => handleResetPinCodeUserAdmin(user),
|
||||
};
|
||||
|
||||
-1
@@ -315,7 +315,6 @@
|
||||
|
||||
const Close = $derived({
|
||||
title: $t('go_back'),
|
||||
type: $t('command'),
|
||||
icon: mdiArrowLeft,
|
||||
onAction: handleEscape,
|
||||
$if: () => !assetViewerManager.isViewing,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { afterNavigate, beforeNavigate, goto } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { shortcut } from '$lib/actions/shortcut';
|
||||
import DownloadPanel from '$lib/components/asset-viewer/download-panel.svelte';
|
||||
import ErrorLayout from '$lib/components/layouts/ErrorLayout.svelte';
|
||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||
@@ -22,15 +21,27 @@
|
||||
import { isAssetViewerRoute } from '$lib/utils/navigation';
|
||||
import { getServerConfig } from '@immich/sdk';
|
||||
import {
|
||||
CommandPaletteDefaultProvider,
|
||||
TooltipProvider,
|
||||
CommandPaletteProvider,
|
||||
defaultProvider,
|
||||
modalManager,
|
||||
screencastManager,
|
||||
ScreencastOverlay,
|
||||
setLocale,
|
||||
setTranslations,
|
||||
siteCommands,
|
||||
toastManager,
|
||||
TooltipProvider,
|
||||
type ActionItem,
|
||||
} from '@immich/ui';
|
||||
import { mdiAccountMultipleOutline, mdiBookshelf, mdiCog, mdiServer, mdiSync, mdiThemeLightDark } from '@mdi/js';
|
||||
import {
|
||||
mdiAccountMultipleOutline,
|
||||
mdiBookshelf,
|
||||
mdiCog,
|
||||
mdiKeyboard,
|
||||
mdiServer,
|
||||
mdiSync,
|
||||
mdiThemeLightDark,
|
||||
} from '@mdi/js';
|
||||
import { onMount, type Snippet } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
@@ -139,26 +150,37 @@
|
||||
}
|
||||
};
|
||||
|
||||
const userCommands: ActionItem[] = [
|
||||
const commands: ActionItem[] = [
|
||||
{
|
||||
title: $t('theme'),
|
||||
description: $t('toggle_theme_description'),
|
||||
type: $t('command'),
|
||||
icon: mdiThemeLightDark,
|
||||
onAction: () => themeManager.toggleTheme(),
|
||||
shortcuts: { shift: true, key: 't' },
|
||||
},
|
||||
{
|
||||
title: $t('screencast_mode_title'),
|
||||
description: $t('screencast_mode_description'),
|
||||
icon: mdiKeyboard,
|
||||
onAction: () => screencastManager.toggle(),
|
||||
},
|
||||
{
|
||||
title: $t('my_immich_title'),
|
||||
description: $t('my_immich_description'),
|
||||
onAction: () => copyToClipboard(getMyImmichLink().toString()),
|
||||
shortcuts: { ctrl: true, shift: true, key: 'm' },
|
||||
},
|
||||
];
|
||||
|
||||
const adminCommands: ActionItem[] = [
|
||||
const adminPages: ActionItem[] = [
|
||||
{
|
||||
title: $t('users'),
|
||||
title: $t('admin.user_management'),
|
||||
description: $t('admin.users_page_description'),
|
||||
icon: mdiAccountMultipleOutline,
|
||||
onAction: () => goto(Route.users()),
|
||||
},
|
||||
{
|
||||
title: $t('settings'),
|
||||
title: $t('admin.system_settings'),
|
||||
description: $t('admin.settings_page_description'),
|
||||
icon: mdiCog,
|
||||
onAction: () => goto(Route.systemSettings()),
|
||||
@@ -167,7 +189,6 @@
|
||||
title: $t('admin.queues'),
|
||||
description: $t('admin.queues_page_description'),
|
||||
icon: mdiSync,
|
||||
type: $t('page'),
|
||||
onAction: () => goto(Route.queues()),
|
||||
},
|
||||
{
|
||||
@@ -182,14 +203,11 @@
|
||||
icon: mdiServer,
|
||||
onAction: () => goto(Route.systemStatistics()),
|
||||
},
|
||||
].map((route) => ({ ...route, type: $t('page'), $if: () => authManager.user.isAdmin }));
|
||||
|
||||
const commands = $derived([...userCommands, ...adminCommands]);
|
||||
].map((route) => ({ ...route, $if: () => authManager.authenticated && authManager.user.isAdmin }));
|
||||
</script>
|
||||
|
||||
<OnEvents {onWebsocketConnect} />
|
||||
|
||||
<CommandPaletteDefaultProvider name="Global" actions={commands} />
|
||||
<VersionAnnouncement />
|
||||
|
||||
<svelte:head>
|
||||
@@ -231,13 +249,6 @@
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<svelte:document
|
||||
use:shortcut={{
|
||||
shortcut: { ctrl: true, shift: true, key: 'm' },
|
||||
onShortcut: () => copyToClipboard(getMyImmichLink().toString()),
|
||||
}}
|
||||
/>
|
||||
|
||||
<TooltipProvider>
|
||||
{#if page.data.error}
|
||||
<ErrorLayout error={page.data.error}></ErrorLayout>
|
||||
@@ -251,4 +262,13 @@
|
||||
|
||||
<DownloadPanel />
|
||||
<UploadPanel />
|
||||
<ScreencastOverlay />
|
||||
|
||||
<CommandPaletteProvider
|
||||
providers={[
|
||||
defaultProvider({ name: $t('command'), actions: commands }),
|
||||
defaultProvider({ name: $t('page'), actions: adminPages }),
|
||||
defaultProvider({ name: $t('link'), actions: siteCommands }),
|
||||
]}
|
||||
/>
|
||||
</TooltipProvider>
|
||||
|
||||
Reference in New Issue
Block a user