diff --git a/web/src/lib/components/QueuePanel.svelte b/web/src/lib/components/QueuePanel.svelte index 177cbf33c3..b52b4941d1 100644 --- a/web/src/lib/components/QueuePanel.svelte +++ b/web/src/lib/components/QueuePanel.svelte @@ -12,6 +12,7 @@ type QueueResponseDto, runQueueCommandLegacy, } from '@immich/sdk'; + import { mdiCheck } from '@mdi/js'; import { modalManager, toastManager } from '@immich/ui'; import type { Component } from 'svelte'; import { t } from 'svelte-i18n'; @@ -112,7 +113,7 @@ switch (dto.command) { case QueueCommand.Empty: { - toastManager.success($t('admin.cleared_jobs', { values: { job: item.title } })); + toastManager.show({ title: $t('success'), description: $t('admin.cleared_jobs', { values: { job: item.title } }), icon: mdiCheck }); break; } } diff --git a/web/src/lib/components/asset-viewer/actions/delete-action.svelte b/web/src/lib/components/asset-viewer/actions/delete-action.svelte index 24ef7d941f..93c5f731ab 100644 --- a/web/src/lib/components/asset-viewer/actions/delete-action.svelte +++ b/web/src/lib/components/asset-viewer/actions/delete-action.svelte @@ -9,7 +9,7 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { deleteAssets, type AssetResponseDto } from '@immich/sdk'; import { IconButton, modalManager, toastManager } from '@immich/ui'; - import { mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js'; + import { mdiCheck, mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { OnAction, PreAction } from './action'; @@ -40,7 +40,7 @@ preAction({ type: AssetAction.DELETE, asset: timelineAsset }); await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } }); onAction({ type: AssetAction.DELETE, asset: timelineAsset }); - toastManager.success($t('permanently_deleted_asset')); + toastManager.show({ title: $t('success'), description: $t('permanently_deleted_asset'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_delete_asset')); } diff --git a/web/src/lib/components/asset-viewer/actions/restore-action.svelte b/web/src/lib/components/asset-viewer/actions/restore-action.svelte index 311eab461b..f9280c8587 100644 --- a/web/src/lib/components/asset-viewer/actions/restore-action.svelte +++ b/web/src/lib/components/asset-viewer/actions/restore-action.svelte @@ -5,7 +5,7 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { restoreAssets, type AssetResponseDto } from '@immich/sdk'; import { toastManager } from '@immich/ui'; - import { mdiHistory } from '@mdi/js'; + import { mdiCheck, mdiHistory } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { OnAction } from './action'; @@ -21,7 +21,7 @@ await restoreAssets({ bulkIdsDto: { ids: [asset.id] } }); asset.isTrashed = false; onAction({ type: AssetAction.RESTORE, asset: toTimelineAsset(asset) }); - toastManager.success($t('restored_asset')); + toastManager.show({ title: $t('success'), description: $t('restored_asset'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_restore_assets')); } diff --git a/web/src/lib/components/asset-viewer/actions/set-album-cover-action.svelte b/web/src/lib/components/asset-viewer/actions/set-album-cover-action.svelte index 22ca22b0d9..caf1d6df13 100644 --- a/web/src/lib/components/asset-viewer/actions/set-album-cover-action.svelte +++ b/web/src/lib/components/asset-viewer/actions/set-album-cover-action.svelte @@ -3,7 +3,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updateAlbumInfo, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk'; import { toastManager } from '@immich/ui'; - import { mdiImageOutline } from '@mdi/js'; + import { mdiCheck, mdiImageOutline } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -21,7 +21,7 @@ albumThumbnailAssetId: asset.id, }, }); - toastManager.success($t('album_cover_updated')); + toastManager.show({ title: $t('success'), description: $t('album_cover_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_album_cover')); } diff --git a/web/src/lib/components/asset-viewer/actions/set-person-featured-action.svelte b/web/src/lib/components/asset-viewer/actions/set-person-featured-action.svelte index dcc8921a34..e09847f9a6 100644 --- a/web/src/lib/components/asset-viewer/actions/set-person-featured-action.svelte +++ b/web/src/lib/components/asset-viewer/actions/set-person-featured-action.svelte @@ -4,7 +4,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updatePerson, type AssetResponseDto, type PersonResponseDto } from '@immich/sdk'; import { toastManager } from '@immich/ui'; - import { mdiFaceManProfile } from '@mdi/js'; + import { mdiCheck, mdiFaceManProfile } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { OnAction } from './action'; @@ -31,7 +31,7 @@ person, }); - toastManager.success($t('feature_photo_updated')); + toastManager.show({ title: $t('success'), description: $t('feature_photo_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_set_feature_photo')); } diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index bdf5a06b27..ad4db7e76e 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -13,7 +13,7 @@ import { isTenMinutesApart } from '$lib/utils/timesince'; import { ReactionType, type ActivityResponseDto, type AssetTypeEnum, type UserResponseDto } from '@immich/sdk'; import { Icon, IconButton, LoadingSpinner, Textarea, toastManager } from '@immich/ui'; - import { mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiSend, mdiThumbUp } from '@mdi/js'; + import { mdiCheck, mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiSend, mdiThumbUp } from '@mdi/js'; import * as luxon from 'luxon'; import { t } from 'svelte-i18n'; import { fromAction } from 'svelte/attachments'; @@ -74,7 +74,7 @@ [ReactionType.Comment]: $t('comment_deleted'), [ReactionType.Like]: $t('like_deleted'), }; - toastManager.success(deleteMessages[reaction.type]); + toastManager.show({ title: $t('success'), description: deleteMessages[reaction.type], icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_remove_reaction')); } diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 118d1a52f8..5bd146ab90 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -37,6 +37,7 @@ type StackResponseDto, } from '@immich/sdk'; import { toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { onDestroy, onMount, untrack } from 'svelte'; import { t } from 'svelte-i18n'; import { fly } from 'svelte/transition'; @@ -265,7 +266,7 @@ const handleRunJob = async (name: AssetJobName) => { try { await runAssetJobs({ assetJobsDto: { assetIds: [asset.id], name } }); - toastManager.success($getAssetJobMessage(name)); + toastManager.show({ title: $t('success'), description: $getAssetJobMessage(name), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_submit_job')); } diff --git a/web/src/lib/components/asset-viewer/detail-panel-description.svelte b/web/src/lib/components/asset-viewer/detail-panel-description.svelte index a1ffd8441b..e32a1f9a47 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-description.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-description.svelte @@ -22,7 +22,10 @@ } try { await updateAsset({ id: asset.id, updateAssetDto: { description } }); - toastManager.success($t('asset_description_updated')); + toastManager.show({ + title: $t('success'), + description: $t('asset_description_updated'), + }); } catch (error) { handleError(error, $t('cannot_update_the_description')); } diff --git a/web/src/lib/components/faces-page/manage-people-visibility.svelte b/web/src/lib/components/faces-page/manage-people-visibility.svelte index 5771766f64..846e631ac8 100644 --- a/web/src/lib/components/faces-page/manage-people-visibility.svelte +++ b/web/src/lib/components/faces-page/manage-people-visibility.svelte @@ -8,7 +8,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updatePeople, type PersonResponseDto } from '@immich/sdk'; import { Button, IconButton, toastManager } from '@immich/ui'; - import { mdiClose, mdiEye, mdiEyeOff, mdiEyeSettings, mdiRestart } from '@mdi/js'; + import { mdiCheck, mdiClose, mdiEye, mdiEyeOff, mdiEyeSettings, mdiRestart } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -72,7 +72,7 @@ if (failCount > 0) { toastManager.warning($t('errors.unable_to_change_visibility', { values: { count: failCount } })); } - toastManager.success($t('visibility_changed', { values: { count: successCount } })); + toastManager.show({ title: $t('success'), description: $t('visibility_changed', { values: { count: successCount } }), icon: mdiCheck }); } for (const person of people) { diff --git a/web/src/lib/components/faces-page/merge-face-selector.svelte b/web/src/lib/components/faces-page/merge-face-selector.svelte index efec16173b..6220de3c83 100644 --- a/web/src/lib/components/faces-page/merge-face-selector.svelte +++ b/web/src/lib/components/faces-page/merge-face-selector.svelte @@ -5,7 +5,7 @@ import { handleError } from '$lib/utils/handle-error'; import { getAllPeople, getPerson, mergePerson, type PersonResponseDto } from '@immich/sdk'; import { Button, Icon, IconButton, modalManager, toastManager } from '@immich/ui'; - import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js'; + import { mdiCallMerge, mdiCheck, mdiMerge, mdiSwapHorizontal } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; import { flip } from 'svelte/animate'; @@ -74,7 +74,7 @@ }); const mergedPerson = await getPerson({ id: person.id }); const count = results.filter(({ success }) => success).length; - toastManager.success($t('merged_people_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('merged_people_count', { values: { count } }), icon: mdiCheck }); onMerge(mergedPerson); } catch (error) { handleError(error, $t('cannot_merge_people')); diff --git a/web/src/lib/components/faces-page/person-side-panel.svelte b/web/src/lib/components/faces-page/person-side-panel.svelte index 6a0d467124..65da3ed5e5 100644 --- a/web/src/lib/components/faces-page/person-side-panel.svelte +++ b/web/src/lib/components/faces-page/person-side-panel.svelte @@ -18,7 +18,7 @@ type PersonResponseDto, } from '@immich/sdk'; import { Icon, IconButton, LoadingSpinner, modalManager, toastManager } from '@immich/ui'; - import { mdiAccountOff, mdiArrowLeftThin, mdiPencil, mdiRestart, mdiTrashCan } from '@mdi/js'; + import { mdiAccountOff, mdiArrowLeftThin, mdiCheck, mdiPencil, mdiRestart, mdiTrashCan } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; import { linear } from 'svelte/easing'; @@ -126,7 +126,7 @@ } } - toastManager.success($t('people_edits_count', { values: { count: numberOfChanges } })); + toastManager.show({ title: $t('success'), description: $t('people_edits_count', { values: { count: numberOfChanges } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.cant_apply_changes')); } diff --git a/web/src/lib/components/faces-page/unmerge-face-selector.svelte b/web/src/lib/components/faces-page/unmerge-face-selector.svelte index f12df74730..809d35596b 100644 --- a/web/src/lib/components/faces-page/unmerge-face-selector.svelte +++ b/web/src/lib/components/faces-page/unmerge-face-selector.svelte @@ -9,7 +9,7 @@ type PersonResponseDto, } from '@immich/sdk'; import { Button, toastManager } from '@immich/ui'; - import { mdiMerge, mdiPlus } from '@mdi/js'; + import { mdiCheck, mdiMerge, mdiPlus } from '@mdi/js'; import { onMount, type Snippet } from 'svelte'; import { t } from 'svelte-i18n'; import { quintOut } from 'svelte/easing'; @@ -71,7 +71,7 @@ disableButtons = true; const data = await createPerson({ personCreateDto: {} }); await reassignFaces({ id: data.id, assetFaceUpdateDto: { data: selectedPeople } }); - toastManager.success($t('reassigned_assets_to_new_person', { values: { count: assetIds.length } })); + toastManager.show({ title: $t('success'), description: $t('reassigned_assets_to_new_person', { values: { count: assetIds.length } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_reassign_assets_new_person')); } finally { @@ -88,11 +88,13 @@ disableButtons = true; if (selectedPerson) { await reassignFaces({ id: selectedPerson.id, assetFaceUpdateDto: { data: selectedPeople } }); - toastManager.success( - $t('reassigned_assets_to_existing_person', { + toastManager.show({ + title: $t('success'), + description: $t('reassigned_assets_to_existing_person', { values: { count: assetIds.length, name: selectedPerson.name || null }, }), - ); + icon: mdiCheck, + }); } } catch (error) { handleError( diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte index ff1597fedb..5b1c646499 100644 --- a/web/src/lib/components/memory-page/memory-viewer.svelte +++ b/web/src/lib/components/memory-page/memory-viewer.svelte @@ -36,6 +36,7 @@ import { IconButton, toastManager } from '@immich/ui'; import { mdiCardsOutline, + mdiCheck, mdiChevronDown, mdiChevronLeft, mdiChevronRight, @@ -201,7 +202,7 @@ } await memoryStore.deleteMemory(current.memory.id); - toastManager.success($t('removed_memory')); + toastManager.show({ title: $t('success'), description: $t('removed_memory'), icon: mdiCheck }); init(page); }; @@ -212,7 +213,7 @@ const newSavedState = !current.memory.isSaved; await memoryStore.updateMemorySaved(current.memory.id, newSavedState); - toastManager.success(newSavedState ? $t('added_to_favorites') : $t('removed_from_favorites')); + toastManager.show({ title: $t('success'), description: newSavedState ? $t('added_to_favorites') : $t('removed_from_favorites'), icon: newSavedState ? mdiHeart : mdiHeartOutline }); init(page); }; diff --git a/web/src/lib/components/share-page/individual-shared-viewer.svelte b/web/src/lib/components/share-page/individual-shared-viewer.svelte index 14817d3bd5..a34e75a55e 100644 --- a/web/src/lib/components/share-page/individual-shared-viewer.svelte +++ b/web/src/lib/components/share-page/individual-shared-viewer.svelte @@ -17,7 +17,7 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { addSharedLinkAssets, getAssetInfo, type SharedLinkResponseDto } from '@immich/sdk'; import { IconButton, Logo, toastManager } from '@immich/ui'; - import { mdiArrowLeft, mdiDownload, mdiFileImagePlusOutline, mdiSelectAll } from '@mdi/js'; + import { mdiArrowLeft, mdiCheck, mdiDownload, mdiFileImagePlusOutline, mdiSelectAll } from '@mdi/js'; import { t } from 'svelte-i18n'; import ControlAppBar from '../shared-components/control-app-bar.svelte'; import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte'; @@ -61,7 +61,7 @@ const added = data.filter((item) => item.success).length; - toastManager.success($t('assets_added_count', { values: { count: added } })); + toastManager.show({ title: $t('success'), description: $t('assets_added_count', { values: { count: added } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_add_assets_to_shared_link')); } diff --git a/web/src/lib/components/shared-components/upload-panel.svelte b/web/src/lib/components/shared-components/upload-panel.svelte index 13b980f085..70e3c255f2 100644 --- a/web/src/lib/components/shared-components/upload-panel.svelte +++ b/web/src/lib/components/shared-components/upload-panel.svelte @@ -3,7 +3,7 @@ import { uploadAssetsStore } from '$lib/stores/upload'; import { uploadExecutionQueue } from '$lib/utils/file-uploader'; import { Icon, IconButton, toastManager } from '@immich/ui'; - import { mdiCancel, mdiCloudUploadOutline, mdiCog, mdiWindowMinimize } from '@mdi/js'; + import { mdiCancel, mdiCheck, mdiCloudUploadOutline, mdiCog, mdiWindowMinimize } from '@mdi/js'; import { t } from 'svelte-i18n'; import { quartInOut } from 'svelte/easing'; import { fade, scale } from 'svelte/transition'; @@ -30,7 +30,7 @@ if ($stats.errors > 0) { toastManager.danger($t('upload_errors', { values: { count: $stats.errors } })); } else if ($stats.success > 0) { - toastManager.success($t('upload_success')); + toastManager.show({ title: $t('success'), description: $t('upload_success'), icon: mdiCheck }); } if ($stats.duplicates > 0) { toastManager.warning($t('upload_skipped_duplicates', { values: { count: $stats.duplicates } })); diff --git a/web/src/lib/components/timeline/actions/AssetJobActions.svelte b/web/src/lib/components/timeline/actions/AssetJobActions.svelte index 249b3c5d14..6389ca6e23 100644 --- a/web/src/lib/components/timeline/actions/AssetJobActions.svelte +++ b/web/src/lib/components/timeline/actions/AssetJobActions.svelte @@ -5,6 +5,7 @@ import { handleError } from '$lib/utils/handle-error'; import { AssetJobName, runAssetJobs } from '@immich/sdk'; import { toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -22,7 +23,7 @@ try { const ids = [...getOwnedAssets()].map(({ id }) => id); await runAssetJobs({ assetJobsDto: { assetIds: ids, name } }); - toastManager.success($getAssetJobMessage(name)); + toastManager.show({ title: $t('success'), description: $getAssetJobMessage(name), icon: mdiCheck }); clearSelect(); } catch (error) { handleError(error, $t('errors.unable_to_submit_job')); diff --git a/web/src/lib/components/timeline/actions/FavoriteAction.svelte b/web/src/lib/components/timeline/actions/FavoriteAction.svelte index e1f09fed13..b4b52659d9 100644 --- a/web/src/lib/components/timeline/actions/FavoriteAction.svelte +++ b/web/src/lib/components/timeline/actions/FavoriteAction.svelte @@ -5,7 +5,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updateAssets } from '@immich/sdk'; import { IconButton, toastManager } from '@immich/ui'; - import { mdiHeartMinusOutline, mdiHeartOutline, mdiTimerSand } from '@mdi/js'; + import { mdiHeart, mdiHeartMinusOutline, mdiHeartOutline, mdiTimerSand } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -42,11 +42,13 @@ onFavorite?.(ids, isFavorite); - toastManager.success( - isFavorite + toastManager.show({ + title: $t('success'), + description: isFavorite ? $t('added_to_favorites_count', { values: { count: ids.length } }) : $t('removed_from_favorites_count', { values: { count: ids.length } }), - ); + icon: isFavorite ? mdiHeart : mdiHeartOutline, + }); clearSelect(); } catch (error) { diff --git a/web/src/lib/components/timeline/actions/RemoveFromAlbumAction.svelte b/web/src/lib/components/timeline/actions/RemoveFromAlbumAction.svelte index 9a65426193..4b8e7875a3 100644 --- a/web/src/lib/components/timeline/actions/RemoveFromAlbumAction.svelte +++ b/web/src/lib/components/timeline/actions/RemoveFromAlbumAction.svelte @@ -3,7 +3,7 @@ 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 { mdiCheck, mdiDeleteOutline, mdiImageRemoveOutline } from '@mdi/js'; import { t } from 'svelte-i18n'; import MenuOption from '../../shared-components/context-menu/menu-option.svelte'; @@ -38,7 +38,7 @@ onRemove?.(ids); const count = results.filter(({ success }) => success).length; - toastManager.success($t('assets_removed_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('assets_removed_count', { values: { count } }), icon: mdiCheck }); clearSelect(); } catch (error) { diff --git a/web/src/lib/components/timeline/actions/RestoreAction.svelte b/web/src/lib/components/timeline/actions/RestoreAction.svelte index ec70f01cd9..94e7db0786 100644 --- a/web/src/lib/components/timeline/actions/RestoreAction.svelte +++ b/web/src/lib/components/timeline/actions/RestoreAction.svelte @@ -4,7 +4,7 @@ import { handleError } from '$lib/utils/handle-error'; import { restoreAssets } from '@immich/sdk'; import { Button, toastManager } from '@immich/ui'; - import { mdiHistory } from '@mdi/js'; + import { mdiCheck, mdiHistory } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -24,7 +24,7 @@ const ids = [...getAssets()].map((a) => a.id); await restoreAssets({ bulkIdsDto: { ids } }); onRestore?.(ids); - toastManager.success($t('assets_restored_count', { values: { count: ids.length } })); + toastManager.show({ title: $t('success'), description: $t('assets_restored_count', { values: { count: ids.length } }), icon: mdiCheck }); clearSelect(); } catch (error) { handleError(error, $t('errors.unable_to_restore_assets')); diff --git a/web/src/lib/components/user-settings-page/PinCodeChangeForm.svelte b/web/src/lib/components/user-settings-page/PinCodeChangeForm.svelte index 2edb8fa606..b1f0840681 100644 --- a/web/src/lib/components/user-settings-page/PinCodeChangeForm.svelte +++ b/web/src/lib/components/user-settings-page/PinCodeChangeForm.svelte @@ -4,6 +4,7 @@ import { handleError } from '$lib/utils/handle-error'; import { changePinCode } from '@immich/sdk'; import { Button, Heading, modalManager, Text, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; @@ -23,7 +24,7 @@ try { await changePinCode({ pinCodeChangeDto: { pinCode: currentPinCode, newPinCode } }); resetForm(); - toastManager.success($t('pin_code_changed_successfully')); + toastManager.show({ title: $t('success'), description: $t('pin_code_changed_successfully'), icon: mdiCheck }); } catch (error) { handleError(error, $t('unable_to_change_pin_code')); } finally { diff --git a/web/src/lib/components/user-settings-page/PinCodeCreateForm.svelte b/web/src/lib/components/user-settings-page/PinCodeCreateForm.svelte index 3307474401..1c4190ec07 100644 --- a/web/src/lib/components/user-settings-page/PinCodeCreateForm.svelte +++ b/web/src/lib/components/user-settings-page/PinCodeCreateForm.svelte @@ -3,6 +3,7 @@ import { handleError } from '$lib/utils/handle-error'; import { setupPinCode } from '@immich/sdk'; import { Button, Heading, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { @@ -26,7 +27,7 @@ isLoading = true; try { await setupPinCode({ pinCodeSetupDto: { pinCode: newPinCode } }); - toastManager.success($t('pin_code_setup_successfully')); + toastManager.show({ title: $t('success'), description: $t('pin_code_setup_successfully'), icon: mdiCheck }); onCreated?.(newPinCode); resetForm(); } catch (error) { diff --git a/web/src/lib/components/user-settings-page/device-list.svelte b/web/src/lib/components/user-settings-page/device-list.svelte index 0789c7b179..e9a2c77a53 100644 --- a/web/src/lib/components/user-settings-page/device-list.svelte +++ b/web/src/lib/components/user-settings-page/device-list.svelte @@ -2,6 +2,7 @@ import { handleError } from '$lib/utils/handle-error'; import { deleteAllSessions, deleteSession, getSessions, type SessionResponseDto } from '@immich/sdk'; import { Button, modalManager, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; import DeviceCard from './device-card.svelte'; @@ -24,7 +25,7 @@ try { await deleteSession({ id: device.id }); - toastManager.success($t('logged_out_device')); + toastManager.show({ title: $t('success'), description: $t('logged_out_device'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_log_out_device')); } finally { @@ -40,7 +41,7 @@ try { await deleteAllSessions(); - toastManager.success($t('logged_out_all_devices')); + toastManager.show({ title: $t('success'), description: $t('logged_out_all_devices'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_log_out_all_devices')); } finally { diff --git a/web/src/lib/components/user-settings-page/download-settings.svelte b/web/src/lib/components/user-settings-page/download-settings.svelte index 79d6ba6a1d..1a630439d5 100644 --- a/web/src/lib/components/user-settings-page/download-settings.svelte +++ b/web/src/lib/components/user-settings-page/download-settings.svelte @@ -7,6 +7,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updateMyPreferences } from '@immich/sdk'; import { Button, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; @@ -25,7 +26,7 @@ }); $preferences = newPreferences; - toastManager.success($t('saved_settings')); + toastManager.show({ title: $t('success'), description: $t('saved_settings'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_settings')); } diff --git a/web/src/lib/components/user-settings-page/feature-settings.svelte b/web/src/lib/components/user-settings-page/feature-settings.svelte index 3ddf074976..71e09e86db 100644 --- a/web/src/lib/components/user-settings-page/feature-settings.svelte +++ b/web/src/lib/components/user-settings-page/feature-settings.svelte @@ -5,6 +5,7 @@ import { handleError } from '$lib/utils/handle-error'; import { AssetOrder, updateMyPreferences } from '@immich/sdk'; import { Button, Field, NumberInput, Switch, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; @@ -54,7 +55,7 @@ $preferences = { ...data }; - toastManager.success($t('saved_settings')); + toastManager.show({ title: $t('success'), description: $t('saved_settings'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_settings')); } diff --git a/web/src/lib/components/user-settings-page/notifications-settings.svelte b/web/src/lib/components/user-settings-page/notifications-settings.svelte index a2f9c472d4..396130b538 100644 --- a/web/src/lib/components/user-settings-page/notifications-settings.svelte +++ b/web/src/lib/components/user-settings-page/notifications-settings.svelte @@ -3,6 +3,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updateMyPreferences } from '@immich/sdk'; import { Button, Field, Switch, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; @@ -26,7 +27,7 @@ $preferences.emailNotifications.albumInvite = data.emailNotifications.albumInvite; $preferences.emailNotifications.albumUpdate = data.emailNotifications.albumUpdate; - toastManager.success($t('saved_settings')); + toastManager.show({ title: $t('success'), description: $t('saved_settings'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_settings')); } diff --git a/web/src/lib/components/user-settings-page/oauth-settings.svelte b/web/src/lib/components/user-settings-page/oauth-settings.svelte index f881c4cd65..9b7c599c51 100644 --- a/web/src/lib/components/user-settings-page/oauth-settings.svelte +++ b/web/src/lib/components/user-settings-page/oauth-settings.svelte @@ -5,6 +5,7 @@ import { handleError } from '$lib/utils/handle-error'; import { type UserAdminResponseDto } from '@immich/sdk'; import { Button, LoadingSpinner, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; @@ -22,7 +23,7 @@ try { loading = true; user = await oauth.link(globalThis.location); - toastManager.success($t('linked_oauth_account')); + toastManager.show({ title: $t('success'), description: $t('linked_oauth_account'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_link_oauth_account')); } finally { @@ -36,7 +37,7 @@ const handleUnlink = async () => { try { user = await oauth.unlink(); - toastManager.success($t('unlinked_oauth_account')); + toastManager.show({ title: $t('success'), description: $t('unlinked_oauth_account'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_unlink_account')); } diff --git a/web/src/lib/components/user-settings-page/user-profile-settings.svelte b/web/src/lib/components/user-settings-page/user-profile-settings.svelte index 2fb2be8107..4add075e6a 100644 --- a/web/src/lib/components/user-settings-page/user-profile-settings.svelte +++ b/web/src/lib/components/user-settings-page/user-profile-settings.svelte @@ -3,6 +3,7 @@ import { handleError } from '$lib/utils/handle-error'; import { updateMyUser } from '@immich/sdk'; import { Button, Field, Input, toastManager } from '@immich/ui'; + import { mdiCheck } from '@mdi/js'; import { cloneDeep } from 'lodash-es'; import { t } from 'svelte-i18n'; import { createBubbler, preventDefault } from 'svelte/legacy'; @@ -23,7 +24,7 @@ Object.assign(editedUser, data); $user = data; - toastManager.success($t('saved_profile')); + toastManager.show({ title: $t('success'), description: $t('saved_profile'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_save_profile')); } diff --git a/web/src/lib/managers/edit/edit-manager.svelte.ts b/web/src/lib/managers/edit/edit-manager.svelte.ts index b8ebea1cf0..7e3632489c 100644 --- a/web/src/lib/managers/edit/edit-manager.svelte.ts +++ b/web/src/lib/managers/edit/edit-manager.svelte.ts @@ -3,7 +3,7 @@ import { transformManager } from '$lib/managers/edit/transform-manager.svelte'; import { waitForWebsocketEvent } from '$lib/stores/websocket'; import { editAsset, removeAssetEdits, type AssetEditsDto, type AssetResponseDto } from '@immich/sdk'; import { ConfirmModal, modalManager, toastManager } from '@immich/ui'; -import { mdiCropRotate } from '@mdi/js'; +import { mdiCheck, mdiCropRotate } from '@mdi/js'; import type { Component } from 'svelte'; export type EditAction = AssetEditsDto['edits'][number]; @@ -129,7 +129,7 @@ export class EditManager { })); await editCompleted; - toastManager.success('Edits applied successfully'); + toastManager.show({ title: 'Success', description: 'Edits applied successfully', icon: mdiCheck }); this.hasAppliedEdits = true; return true; diff --git a/web/src/lib/services/album.service.ts b/web/src/lib/services/album.service.ts index e1ad368cf7..0401fb4e06 100644 --- a/web/src/lib/services/album.service.ts +++ b/web/src/lib/services/album.service.ts @@ -19,7 +19,7 @@ import { type UpdateAlbumDto, } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiPlusBoxOutline, mdiShareVariantOutline, mdiUpload } from '@mdi/js'; +import { mdiCheck, mdiPlusBoxOutline, mdiShareVariantOutline, mdiUpload } from '@mdi/js'; import { type MessageFormatter } from 'svelte-i18n'; import { get } from 'svelte/store'; @@ -65,7 +65,7 @@ const addAssets = async (album: AlbumResponseDto, assets: TimelineAsset[]) => { const results = await addAssetsToAlbum({ id: album.id, bulkIdsDto: { ids: assetIds } }); const count = results.filter(({ success }) => success).length; - toastManager.success($t('assets_added_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('assets_added_count', { values: { count } }), icon: mdiCheck }); eventManager.emit('AlbumAddAssets'); } catch (error) { handleError(error, $t('errors.error_adding_assets_to_album')); @@ -134,7 +134,7 @@ export const handleDeleteAlbum = async (album: AlbumResponseDto, options?: { pro await deleteAlbum({ id: album.id }); eventManager.emit('AlbumDelete', album); if (notify) { - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('album_deleted'), icon: mdiCheck }); } return true; } catch (error) { diff --git a/web/src/lib/services/api-key.service.ts b/web/src/lib/services/api-key.service.ts index dec333c0bc..23b64cab4d 100644 --- a/web/src/lib/services/api-key.service.ts +++ b/web/src/lib/services/api-key.service.ts @@ -12,7 +12,7 @@ import { type ApiKeyUpdateDto, } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiPencilOutline, mdiPlus, mdiTrashCanOutline } from '@mdi/js'; +import { mdiCheck, mdiPencilOutline, mdiPlus, mdiTrashCanOutline } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export const getApiKeysActions = ($t: MessageFormatter) => { @@ -80,7 +80,7 @@ export const handleUpdateApiKey = async (apiKey: { id: string }, dto: ApiKeyUpda try { const response = await updateApiKey({ id: apiKey.id, apiKeyUpdateDto: dto }); eventManager.emit('ApiKeyUpdate', response); - toastManager.success($t('saved_api_key')); + toastManager.show({ title: $t('success'), description: $t('saved_api_key'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_save_api_key')); @@ -98,7 +98,7 @@ export const handleDeleteApiKey = async (apiKey: ApiKeyResponseDto) => { try { await deleteApiKey({ id: apiKey.id }); eventManager.emit('ApiKeyDelete', apiKey); - toastManager.success($t('removed_api_key', { values: { name: apiKey.name } })); + toastManager.show({ title: $t('success'), description: $t('removed_api_key', { values: { name: apiKey.name } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_remove_api_key')); } diff --git a/web/src/lib/services/asset.service.ts b/web/src/lib/services/asset.service.ts index 81b74e51e2..5e9d59c078 100644 --- a/web/src/lib/services/asset.service.ts +++ b/web/src/lib/services/asset.service.ts @@ -21,6 +21,7 @@ import { import { modalManager, toastManager, type ActionItem } from '@immich/ui'; import { mdiAlertOutline, + mdiCheck, mdiDownload, mdiHeart, mdiHeartOutline, @@ -153,7 +154,7 @@ export const handleDownloadAsset = async (asset: AssetResponseDto) => { } try { - toastManager.success($t('downloading_asset_filename', { values: { filename: asset.originalFileName } })); + toastManager.show({ title: $t('success'), description: $t('downloading_asset_filename', { values: { filename: asset.originalFileName } }), icon: mdiDownload }); downloadUrl(getBaseUrl() + `/assets/${id}/original` + (queryParams ? `?${queryParams}` : ''), filename); } catch (error) { handleError(error, $t('errors.error_downloading', { values: { filename } })); @@ -166,7 +167,7 @@ const handleFavorite = async (asset: AssetResponseDto) => { try { const response = await updateAsset({ id: asset.id, updateAssetDto: { isFavorite: true } }); - toastManager.success($t('added_to_favorites')); + toastManager.show({ title: $t('success'), description: $t('added_to_favorites'), icon: mdiHeart }); eventManager.emit('AssetUpdate', response); } catch (error) { handleError(error, $t('errors.unable_to_add_remove_favorites', { values: { favorite: asset.isFavorite } })); @@ -178,7 +179,7 @@ const handleUnfavorite = async (asset: AssetResponseDto) => { try { const response = await updateAsset({ id: asset.id, updateAssetDto: { isFavorite: false } }); - toastManager.success($t('removed_from_favorites')); + toastManager.show({ title: $t('success'), description: $t('removed_from_favorites'), icon: mdiHeartOutline }); eventManager.emit('AssetUpdate', response); } catch (error) { handleError(error, $t('errors.unable_to_add_remove_favorites', { values: { favorite: asset.isFavorite } })); diff --git a/web/src/lib/services/job.service.ts b/web/src/lib/services/job.service.ts index 3241afc5b0..ae719c8dfd 100644 --- a/web/src/lib/services/job.service.ts +++ b/web/src/lib/services/job.service.ts @@ -2,13 +2,14 @@ import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { createJob, type JobCreateDto } from '@immich/sdk'; import { toastManager } from '@immich/ui'; +import { mdiCheck } from '@mdi/js'; export const handleCreateJob = async (dto: JobCreateDto) => { const $t = await getFormatter(); try { await createJob({ jobCreateDto: dto }); - toastManager.success($t('admin.job_created')); + toastManager.show({ title: $t('success'), description: $t('admin.job_created'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_submit_job')); diff --git a/web/src/lib/services/library.service.ts b/web/src/lib/services/library.service.ts index b427390721..9dc8f5999c 100644 --- a/web/src/lib/services/library.service.ts +++ b/web/src/lib/services/library.service.ts @@ -20,7 +20,7 @@ import { type UpdateLibraryDto, } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiPencilOutline, mdiPlusBoxOutline, mdiSync, mdiTrashCanOutline } from '@mdi/js'; +import { mdiCheck, mdiPencilOutline, mdiPlusBoxOutline, mdiSync, mdiTrashCanOutline } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export const getLibrariesActions = ($t: MessageFormatter, libraries: LibraryResponseDto[]) => { @@ -158,7 +158,7 @@ export const handleCreateLibrary = async (dto: CreateLibraryDto) => { try { const library = await createLibrary({ createLibraryDto: dto }); eventManager.emit('LibraryCreate', library); - toastManager.success($t('admin.library_created', { values: { library: library.name } })); + toastManager.show({ title: $t('success'), description: $t('admin.library_created', { values: { library: library.name } }), icon: mdiCheck }); return library; } catch (error) { handleError(error, $t('errors.unable_to_create_library')); @@ -171,7 +171,7 @@ export const handleUpdateLibrary = async (library: LibraryResponseDto, dto: Upda try { const updatedLibrary = await updateLibrary({ id: library.id, updateLibraryDto: dto }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_update_library')); @@ -202,7 +202,7 @@ const handleDeleteLibrary = async (library: LibraryResponseDto) => { try { await deleteLibrary({ id: library.id }); eventManager.emit('LibraryDelete', { id: library.id }); - toastManager.success($t('admin.library_deleted')); + toastManager.show({ title: $t('success'), description: $t('admin.library_deleted'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_remove_library')); } @@ -222,7 +222,7 @@ export const handleAddLibraryFolder = async (library: LibraryResponseDto, folder updateLibraryDto: { importPaths: [...library.importPaths, folder] }, }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); return false; @@ -243,7 +243,7 @@ export const handleEditLibraryFolder = async (library: LibraryResponseDto, oldVa try { const updatedLibrary = await updateLibrary({ id: library.id, updateLibraryDto: { importPaths } }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); return false; @@ -270,7 +270,7 @@ const handleDeleteLibraryFolder = async (library: LibraryResponseDto, folder: st updateLibraryDto: { importPaths: library.importPaths.filter((path) => path !== folder) }, }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); } @@ -290,7 +290,7 @@ export const handleAddLibraryExclusionPattern = async (library: LibraryResponseD updateLibraryDto: { exclusionPatterns: [...library.exclusionPatterns, exclusionPattern] }, }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); return false; @@ -311,7 +311,7 @@ export const handleEditExclusionPattern = async (library: LibraryResponseDto, ol try { const updatedLibrary = await updateLibrary({ id: library.id, updateLibraryDto: { exclusionPatterns } }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); return false; @@ -336,7 +336,7 @@ const handleDeleteExclusionPattern = async (library: LibraryResponseDto, exclusi }, }); eventManager.emit('LibraryUpdate', updatedLibrary); - toastManager.success($t('admin.library_updated')); + toastManager.show({ title: $t('success'), description: $t('admin.library_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); } diff --git a/web/src/lib/services/person.service.ts b/web/src/lib/services/person.service.ts index f6b8289f13..0ae3f60601 100644 --- a/web/src/lib/services/person.service.ts +++ b/web/src/lib/services/person.service.ts @@ -4,7 +4,7 @@ import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { updatePerson, type PersonResponseDto } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiCalendarEditOutline } from '@mdi/js'; +import { mdiCalendarEditOutline, mdiCheck } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export const getPersonActions = ($t: MessageFormatter, person: PersonResponseDto) => { @@ -22,7 +22,7 @@ export const handleUpdatePersonBirthDate = async (person: PersonResponseDto, bir try { const response = await updatePerson({ id: person.id, personUpdateDto: { birthDate } }); - toastManager.success($t('date_of_birth_saved')); + toastManager.show({ title: $t('success'), description: $t('date_of_birth_saved'), icon: mdiCheck }); eventManager.emit('PersonUpdate', response); return true; } catch (error) { diff --git a/web/src/lib/services/queue.service.ts b/web/src/lib/services/queue.service.ts index 19e84b071b..1c61bc4b50 100644 --- a/web/src/lib/services/queue.service.ts +++ b/web/src/lib/services/queue.service.ts @@ -17,6 +17,7 @@ import { } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem, type IconLike } from '@immich/ui'; import { + mdiCheck, mdiClose, mdiCog, mdiContentDuplicate, @@ -128,7 +129,7 @@ export const handleEmptyQueue = async (queue: QueueResponseDto) => { await emptyQueue({ name: queue.name, queueDeleteDto: { failed: false } }); const response = await getQueue({ name: queue.name }); eventManager.emit('QueueUpdate', response); - toastManager.success($t('admin.cleared_jobs', { values: { job: item.title } })); + toastManager.show({ title: $t('success'), description: $t('admin.cleared_jobs', { values: { job: item.title } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.something_went_wrong')); } @@ -154,7 +155,7 @@ const handleRemoveFailedJobs = async (queue: QueueResponseDto) => { await emptyQueue({ name: queue.name, queueDeleteDto: { failed: true } }); const response = await getQueue({ name: queue.name }); eventManager.emit('QueueUpdate', response); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('admin.failed_jobs_cleared'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.something_went_wrong')); } diff --git a/web/src/lib/services/shared-link.service.ts b/web/src/lib/services/shared-link.service.ts index 50069dc6d8..d7ba9bf4c0 100644 --- a/web/src/lib/services/shared-link.service.ts +++ b/web/src/lib/services/shared-link.service.ts @@ -18,7 +18,7 @@ import { type SharedLinkResponseDto, } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiContentCopy, mdiPencilOutline, mdiQrcode, mdiTrashCanOutline } from '@mdi/js'; +import { mdiCheck, mdiContentCopy, mdiPencilOutline, mdiQrcode, mdiTrashCanOutline } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export const getSharedLinkActions = ($t: MessageFormatter, sharedLink: SharedLinkResponseDto) => { @@ -84,7 +84,7 @@ export const handleUpdateSharedLink = async (sharedLink: SharedLinkResponseDto, const response = await updateSharedLink({ id: sharedLink.id, sharedLinkEditDto: dto }); eventManager.emit('SharedLinkUpdate', { album: sharedLink.album, ...response }); - toastManager.success($t('saved')); + toastManager.show({ title: $t('success'), description: $t('saved'), icon: mdiCheck }); return true; } catch (error) { @@ -107,7 +107,7 @@ const handleDeleteSharedLink = async (sharedLink: SharedLinkResponseDto) => { try { await removeSharedLink({ id: sharedLink.id }); eventManager.emit('SharedLinkDelete', sharedLink); - toastManager.success($t('deleted_shared_link')); + toastManager.show({ title: $t('success'), description: $t('deleted_shared_link'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_delete_shared_link')); } @@ -140,7 +140,7 @@ export const handleRemoveSharedLinkAssets = async (sharedLink: SharedLinkRespons } const count = results.filter((item) => item.success).length; - toastManager.success($t('assets_removed_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('assets_removed_count', { values: { count } }), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_remove_assets_from_shared_link')); diff --git a/web/src/lib/services/system-config.service.ts b/web/src/lib/services/system-config.service.ts index 022ad8b8bb..6ae33f20a7 100644 --- a/web/src/lib/services/system-config.service.ts +++ b/web/src/lib/services/system-config.service.ts @@ -6,7 +6,7 @@ import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { getConfig, updateConfig, type ServerFeaturesDto, type SystemConfigDto } from '@immich/sdk'; import { toastManager, type ActionItem } from '@immich/ui'; -import { mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js'; +import { mdiCheck, mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js'; import { isEqual } from 'lodash-es'; import type { MessageFormatter } from 'svelte-i18n'; @@ -62,7 +62,7 @@ export const handleSystemConfigSave = async (update: Partial) = const newConfig = await updateConfig({ systemConfigDto }); eventManager.emit('SystemConfigUpdate', newConfig); - toastManager.success($t('settings_saved')); + toastManager.show({ title: $t('success'), description: $t('settings_saved'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_save_settings')); } diff --git a/web/src/lib/services/tag.service.ts b/web/src/lib/services/tag.service.ts index bbdc843c46..c8e7fe00fa 100644 --- a/web/src/lib/services/tag.service.ts +++ b/web/src/lib/services/tag.service.ts @@ -6,7 +6,7 @@ import { getFormatter } from '$lib/utils/i18n'; import type { TreeNode } from '$lib/utils/tree-utils'; import { deleteTag, updateTag, upsertTags, type TagUpdateDto } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiPencil, mdiPlus, mdiTrashCanOutline } from '@mdi/js'; +import { mdiCheck, mdiPencil, mdiPlus, mdiTrashCanOutline } from '@mdi/js'; import { type MessageFormatter } from 'svelte-i18n'; export const getTagActions = ($t: MessageFormatter, tag: TreeNode) => { @@ -42,7 +42,7 @@ export const handleCreateTag = async (tagValue: string) => { return; } - toastManager.success($t('tag_created', { values: { tag: tag.value } })); + toastManager.show({ title: $t('success'), description: $t('tag_created', { values: { tag: tag.value } }), icon: mdiCheck }); eventManager.emit('TagCreate', tag); return true; @@ -61,7 +61,7 @@ export const handleUpdateTag = async (tag: TreeNode, dto: TagUpdateDto) => { try { const response = await updateTag({ id: tag.id, tagUpdateDto: dto }); - toastManager.success($t('tag_updated', { values: { tag: tag.value } })); + toastManager.show({ title: $t('success'), description: $t('tag_updated', { values: { tag: tag.value } }), icon: mdiCheck }); eventManager.emit('TagUpdate', response); return true; @@ -91,7 +91,7 @@ const handleDeleteTag = async (tag: TreeNode) => { try { await deleteTag({ id: tagId }); eventManager.emit('TagDelete', tag); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('tag_deleted'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.something_went_wrong')); } diff --git a/web/src/lib/services/trash.service.ts b/web/src/lib/services/trash.service.ts index d9660c2f29..14ab8ded9a 100644 --- a/web/src/lib/services/trash.service.ts +++ b/web/src/lib/services/trash.service.ts @@ -2,7 +2,7 @@ import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { emptyTrash, restoreTrash } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiDeleteForeverOutline, mdiHistory } from '@mdi/js'; +import { mdiCheck, mdiDeleteForeverOutline, mdiHistory } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export const getTrashActions = ($t: MessageFormatter) => { @@ -31,7 +31,7 @@ export const handleEmptyTrash = async () => { try { const { count } = await emptyTrash(); - toastManager.success($t('assets_permanently_deleted_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('assets_permanently_deleted_count', { values: { count } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_empty_trash')); } @@ -47,7 +47,7 @@ export const handleRestoreTrash = async () => { try { const { count } = await restoreTrash(); - toastManager.success($t('assets_restored_count', { values: { count } })); + toastManager.show({ title: $t('success'), description: $t('assets_restored_count', { values: { count } }), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_restore_trash')); } diff --git a/web/src/lib/services/user-admin.service.ts b/web/src/lib/services/user-admin.service.ts index 5fd4ff99fd..e0b31e1e49 100644 --- a/web/src/lib/services/user-admin.service.ts +++ b/web/src/lib/services/user-admin.service.ts @@ -22,6 +22,7 @@ import { } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; import { + mdiCheck, mdiDeleteRestore, mdiLockReset, mdiLockSmart, @@ -101,7 +102,7 @@ export const handleCreateUserAdmin = async (dto: UserAdminCreateDto) => { try { const response = await createUserAdmin({ userAdminCreateDto: dto }); eventManager.emit('UserAdminCreate', response); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('user_created'), icon: mdiCheck }); return response; } catch (error) { handleError(error, $t('errors.unable_to_create_user')); @@ -114,7 +115,7 @@ export const handleUpdateUserAdmin = async (user: UserAdminResponseDto, dto: Use try { const response = await updateUserAdmin({ id: user.id, userAdminUpdateDto: dto }); eventManager.emit('UserAdminUpdate', response); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('user_updated'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_update_user')); @@ -128,7 +129,7 @@ export const handleDeleteUserAdmin = async (user: UserAdminResponseDto, dto: Use try { const result = await deleteUserAdmin({ id: user.id, userAdminDeleteDto: dto }); eventManager.emit('UserAdminDelete', result); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('user_deleted'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_delete_user')); @@ -141,7 +142,7 @@ export const handleRestoreUserAdmin = async (user: UserAdminResponseDto) => { try { const response = await restoreUserAdmin({ id: user.id }); eventManager.emit('UserAdminRestore', response); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('user_restored'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_restore_user')); @@ -182,7 +183,7 @@ const handleResetPasswordUserAdmin = async (user: UserAdminResponseDto) => { const dto = { password: generatePassword(), shouldChangePassword: true }; const response = await updateUserAdmin({ id: user.id, userAdminUpdateDto: dto }); eventManager.emit('UserAdminUpdate', response); - toastManager.success(); + toastManager.show({ title: $t('success'), description: $t('password_reset'), icon: mdiCheck }); await modalManager.show(PasswordResetSuccessModal, { newPassword: dto.password }); } catch (error) { handleError(error, $t('errors.unable_to_reset_password')); @@ -200,7 +201,7 @@ const handleResetPinCodeUserAdmin = async (user: UserAdminResponseDto) => { try { const response = await updateUserAdmin({ id: user.id, userAdminUpdateDto: { pinCode: null } }); eventManager.emit('UserAdminUpdate', response); - toastManager.success($t('pin_code_reset_successfully')); + toastManager.show({ title: $t('success'), description: $t('pin_code_reset_successfully'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_reset_pin_code')); } diff --git a/web/src/lib/services/user.service.ts b/web/src/lib/services/user.service.ts index fbb562b2c0..579922088c 100644 --- a/web/src/lib/services/user.service.ts +++ b/web/src/lib/services/user.service.ts @@ -3,13 +3,14 @@ import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { changePassword, resetPinCode, type ChangePasswordDto, type PinCodeResetDto } from '@immich/sdk'; import { toastManager } from '@immich/ui'; +import { mdiCheck } from '@mdi/js'; export const handleResetPinCode = async (dto: PinCodeResetDto) => { const $t = await getFormatter(); try { await resetPinCode({ pinCodeResetDto: dto }); - toastManager.success($t('pin_code_reset_successfully')); + toastManager.show({ title: $t('success'), description: $t('pin_code_reset_successfully'), icon: mdiCheck }); eventManager.emit('UserPinCodeReset'); return true; } catch (error) { @@ -22,7 +23,7 @@ export const handleChangePassword = async (dto: ChangePasswordDto) => { try { await changePassword({ changePasswordDto: dto }); - toastManager.success($t('updated_password')); + toastManager.show({ title: $t('success'), description: $t('updated_password'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_change_password')); diff --git a/web/src/lib/services/workflow.service.ts b/web/src/lib/services/workflow.service.ts index 9777f1ebcc..6ec02c2996 100644 --- a/web/src/lib/services/workflow.service.ts +++ b/web/src/lib/services/workflow.service.ts @@ -22,7 +22,7 @@ import { type WorkflowUpdateDto, } from '@immich/sdk'; import { modalManager, toastManager, type ActionItem } from '@immich/ui'; -import { mdiCodeJson, mdiDelete, mdiPause, mdiPencil, mdiPlay } from '@mdi/js'; +import { mdiCheck, mdiCodeJson, mdiDelete, mdiPause, mdiPencil, mdiPlay } from '@mdi/js'; import type { MessageFormatter } from 'svelte-i18n'; export type PickerSubType = 'album-picker' | 'people-picker'; @@ -389,7 +389,7 @@ export const handleToggleWorkflowEnabled = async ( }); eventManager.emit('WorkflowUpdate', updated); - toastManager.success($t('workflow_updated')); + toastManager.show({ title: $t('success'), description: $t('workflow_updated'), icon: mdiCheck }); return updated; } catch (error) { handleError(error, $t('errors.unable_to_update_workflow')); @@ -411,7 +411,7 @@ export const handleDeleteWorkflow = async (workflow: WorkflowResponseDto): Promi try { await deleteWorkflow({ id: workflow.id }); eventManager.emit('WorkflowDelete', workflow); - toastManager.success($t('workflow_deleted')); + toastManager.show({ title: $t('success'), description: $t('workflow_deleted'), icon: mdiCheck }); return true; } catch (error) { handleError(error, $t('errors.unable_to_delete_workflow')); 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 afd0ace65b..236c4d555c 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 @@ -73,6 +73,7 @@ mdiAccountEye, mdiAccountEyeOutline, mdiArrowLeft, + mdiCheck, mdiCogOutline, mdiDeleteOutline, mdiDotsVertical, @@ -232,7 +233,7 @@ albumThumbnailAssetId: assetId, }, }); - toastManager.success($t('album_cover_updated')); + toastManager.show({ title: $t('success'), description: $t('album_cover_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_update_album_cover')); } diff --git a/web/src/routes/(user)/people/+page.svelte b/web/src/routes/(user)/people/+page.svelte index 8a325d0d1a..dd68e14597 100644 --- a/web/src/routes/(user)/people/+page.svelte +++ b/web/src/routes/(user)/people/+page.svelte @@ -19,7 +19,7 @@ import { clearQueryParam } from '$lib/utils/navigation'; import { getAllPeople, getPerson, searchPerson, updatePerson, type PersonResponseDto } from '@immich/sdk'; import { Button, Icon, modalManager, toastManager } from '@immich/ui'; - import { mdiAccountOff, mdiEyeOutline } from '@mdi/js'; + import { mdiAccountOff, mdiCheck, mdiEyeOutline, mdiHeart, mdiHeartOutline } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; import { quintOut } from 'svelte/easing'; @@ -157,7 +157,7 @@ break; } } - toastManager.success($t('change_name_successfully')); + toastManager.show({ title: $t('success'), description: $t('change_name_successfully'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_save_name')); } @@ -178,7 +178,7 @@ return person; }); - toastManager.success($t('changed_visibility_successfully')); + toastManager.show({ title: $t('success'), description: $t('changed_visibility_successfully'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_hide_person')); } @@ -198,7 +198,7 @@ return person; }); - toastManager.success(updatedPerson.isFavorite ? $t('added_to_favorites') : $t('removed_from_favorites')); + toastManager.show({ title: $t('success'), description: updatedPerson.isFavorite ? $t('added_to_favorites') : $t('removed_from_favorites'), icon: updatedPerson.isFavorite ? mdiHeart : mdiHeartOutline }); } catch (error) { handleError(error, $t('errors.unable_to_add_remove_favorites', { values: { favorite: detail.isFavorite } })); } 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 48f559ffe6..bf7eab834d 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 @@ -46,9 +46,11 @@ mdiAccountBoxOutline, mdiAccountMultipleCheckOutline, mdiArrowLeft, + mdiCheck, mdiDotsVertical, mdiEyeOffOutline, mdiEyeOutline, + mdiHeart, mdiHeartMinusOutline, mdiHeartOutline, mdiPlus, @@ -150,7 +152,7 @@ personUpdateDto: { isHidden: !person.isHidden }, }); - toastManager.success($t('changed_visibility_successfully')); + toastManager.show({ title: $t('success'), description: $t('changed_visibility_successfully'), icon: mdiCheck }); await goto(previousRoute); } catch (error) { @@ -168,7 +170,7 @@ // Invalidate to reload the page data and have the favorite status updated await invalidateAll(); - toastManager.success(updatedPerson.isFavorite ? $t('added_to_favorites') : $t('removed_from_favorites')); + toastManager.show({ title: $t('success'), description: updatedPerson.isFavorite ? $t('added_to_favorites') : $t('removed_from_favorites'), icon: updatedPerson.isFavorite ? mdiHeart : mdiHeartOutline }); } catch (error) { handleError(error, $t('errors.unable_to_add_remove_favorites', { values: { favorite: person.isFavorite } })); } @@ -187,7 +189,7 @@ } try { person = await updatePerson({ id: person.id, personUpdateDto: { featureFaceAssetId: asset.id } }); - toastManager.success($t('feature_photo_updated')); + toastManager.show({ title: $t('success'), description: $t('feature_photo_updated'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_set_feature_photo')); } @@ -248,7 +250,7 @@ try { person = await updatePerson({ id: person.id, personUpdateDto: { name: personName } }); - toastManager.success($t('change_name_successfully')); + toastManager.show({ title: $t('success'), description: $t('change_name_successfully'), icon: mdiCheck }); } catch (error) { handleError(error, $t('errors.unable_to_save_name')); } diff --git a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte index c6943c6491..0faed51c08 100644 --- a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -17,6 +17,7 @@ import { deleteAssets, deleteDuplicates, updateAssets } from '@immich/sdk'; import { Button, HStack, IconButton, modalManager, Text, toastManager } from '@immich/ui'; import { + mdiCheck, mdiCheckOutline, mdiChevronLeft, mdiChevronRight, @@ -95,7 +96,7 @@ const message = featureFlagsManager.value.trash ? $t('assets_moved_to_trash_count', { values: { count: trashedCount } }) : $t('permanently_deleted_assets_count', { values: { count: trashedCount } }); - toastManager.success(message); + toastManager.show({ title: $t('success'), description: message, icon: mdiCheck }); }; const handleResolve = async (duplicateId: string, duplicateAssetIds: string[], trashIds: string[]) => { @@ -167,7 +168,7 @@ duplicates = []; - toastManager.success($t('resolved_all_duplicates')); + toastManager.show({ title: $t('success'), description: $t('resolved_all_duplicates'), icon: mdiCheck }); page.url.searchParams.delete('index'); await goto(`${AppRoute.DUPLICATES}`); }, diff --git a/web/src/routes/(user)/utilities/workflows/[workflowId]/+page.svelte b/web/src/routes/(user)/utilities/workflows/[workflowId]/+page.svelte index eb47abb767..5a99ab756a 100644 --- a/web/src/routes/(user)/utilities/workflows/[workflowId]/+page.svelte +++ b/web/src/routes/(user)/utilities/workflows/[workflowId]/+page.svelte @@ -44,6 +44,7 @@ } from '@immich/ui'; import { mdiArrowLeft, + mdiCheck, mdiCodeJson, mdiContentSave, mdiFilterOutline, @@ -131,7 +132,10 @@ previousWorkflow = updated; editWorkflow = updated; - toastManager.success($t('workflow_update_success'), { + toastManager.show({ + title: $t('success'), + description: $t('workflow_update_success'), + icon: mdiCheck, closable: true, }); } catch (error) {