mirror of
https://github.com/immich-app/immich.git
synced 2025-12-21 01:11:16 +03:00
feat: toasts (#23298)
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
|
||||
import ToastAction from '$lib/components/ToastAction.svelte';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
import type { StackResponse } from '$lib/utils/asset-utils';
|
||||
import { AssetVisibility, deleteAssets as deleteBulk, restoreAssets } from '@immich/sdk';
|
||||
import { toastManager } from '@immich/ui';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { handleError } from './handle-error';
|
||||
@@ -31,17 +32,27 @@ export const deleteAssets = async (
|
||||
await deleteBulk({ assetBulkDeleteDto: { ids, force } });
|
||||
onAssetDelete(ids);
|
||||
|
||||
notificationController.show({
|
||||
message: force
|
||||
? $t('assets_permanently_deleted_count', { values: { count: ids.length } })
|
||||
: $t('assets_trashed_count', { values: { count: ids.length } }),
|
||||
type: NotificationType.Info,
|
||||
...(onUndoDelete &&
|
||||
!force && {
|
||||
button: { text: $t('undo'), onClick: () => undoDeleteAssets(onUndoDelete, assets) },
|
||||
timeout: 5000,
|
||||
}),
|
||||
});
|
||||
toastManager.custom(
|
||||
{
|
||||
component: ToastAction,
|
||||
props: {
|
||||
title: $t('success'),
|
||||
description: force
|
||||
? $t('assets_permanently_deleted_count')
|
||||
: $t('assets_trashed_count', { values: { count: ids.length } }),
|
||||
color: 'success',
|
||||
button:
|
||||
onUndoDelete && !force
|
||||
? {
|
||||
color: 'secondary',
|
||||
text: $t('undo'),
|
||||
onClick: () => undoDeleteAssets(onUndoDelete, assets),
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
{ timeout: 5000 },
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_delete_assets'));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
|
||||
import ToastAction from '$lib/components/ToastAction.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { downloadManager } from '$lib/managers/download-manager.svelte';
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
type UserPreferencesResponseDto,
|
||||
type UserResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { toastManager } from '@immich/ui';
|
||||
import { DateTime } from 'luxon';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
@@ -57,23 +58,29 @@ export const addAssetsToAlbum = async (albumId: string, assetIds: string[], show
|
||||
const $t = get(t);
|
||||
|
||||
if (showNotification) {
|
||||
let message = $t('assets_cannot_be_added_to_album_count', { values: { count: assetIds.length } });
|
||||
let description = $t('assets_cannot_be_added_to_album_count', { values: { count: assetIds.length } });
|
||||
if (count > 0) {
|
||||
message = $t('assets_added_to_album_count', { values: { count } });
|
||||
description = $t('assets_added_to_album_count', { values: { count } });
|
||||
} else if (duplicateErrorCount > 0) {
|
||||
message = $t('assets_were_part_of_album_count', { values: { count: duplicateErrorCount } });
|
||||
description = $t('assets_were_part_of_album_count', { values: { count: duplicateErrorCount } });
|
||||
}
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
timeout: 5000,
|
||||
message,
|
||||
button: {
|
||||
text: $t('view_album'),
|
||||
onClick() {
|
||||
return goto(`${AppRoute.ALBUMS}/${albumId}`);
|
||||
toastManager.custom(
|
||||
{
|
||||
component: ToastAction,
|
||||
props: {
|
||||
title: $t('info'),
|
||||
color: 'info',
|
||||
description,
|
||||
button: {
|
||||
text: $t('view_album'),
|
||||
onClick() {
|
||||
return goto(`${AppRoute.ALBUMS}/${albumId}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{ timeout: 5000 },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,31 +101,16 @@ export const addAssetsToAlbums = async (albumIds: string[], assetIds: string[],
|
||||
const $t = get(t);
|
||||
|
||||
if (result.error === BulkIdErrorReason.Duplicate) {
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
timeout: 5000,
|
||||
message: $t('assets_were_part_of_albums_count', { values: { count: assetIds.length } }),
|
||||
});
|
||||
toastManager.info($t('assets_were_part_of_albums_count', { values: { count: assetIds.length } }));
|
||||
return result;
|
||||
}
|
||||
if (result.error) {
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
timeout: 5000,
|
||||
message: $t('assets_cannot_be_added_to_albums', { values: { count: assetIds.length } }),
|
||||
});
|
||||
toastManager.warning($t('assets_cannot_be_added_to_albums', { values: { count: assetIds.length } }));
|
||||
return result;
|
||||
}
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
timeout: 5000,
|
||||
message: $t('assets_added_to_albums_count', {
|
||||
values: {
|
||||
albumTotal: albumIds.length,
|
||||
assetTotal: assetIds.length,
|
||||
},
|
||||
}),
|
||||
});
|
||||
toastManager.success(
|
||||
$t('assets_added_to_albums_count', { values: { albumTotal: albumIds.length, assetTotal: assetIds.length } }),
|
||||
);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -136,10 +128,7 @@ export const tagAssets = async ({
|
||||
|
||||
if (showNotification) {
|
||||
const $t = await getFormatter();
|
||||
notificationController.show({
|
||||
message: $t('tagged_assets', { values: { count: assetIds.length } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
toastManager.success($t('tagged_assets', { values: { count: assetIds.length } }));
|
||||
}
|
||||
|
||||
return assetIds;
|
||||
@@ -160,10 +149,7 @@ export const removeTag = async ({
|
||||
|
||||
if (showNotification) {
|
||||
const $t = await getFormatter();
|
||||
notificationController.show({
|
||||
message: $t('removed_tagged_assets', { values: { count: assetIds.length } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
toastManager.success($t('removed_tagged_assets', { values: { count: assetIds.length } }));
|
||||
}
|
||||
|
||||
return assetIds;
|
||||
@@ -286,11 +272,7 @@ export const downloadFile = async (asset: AssetResponseDto) => {
|
||||
}
|
||||
|
||||
try {
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: $t('downloading_asset_filename', { values: { filename: asset.originalFileName } }),
|
||||
});
|
||||
|
||||
toastManager.success($t('downloading_asset_filename', { values: { filename: asset.originalFileName } }));
|
||||
downloadUrl(getBaseUrl() + `/assets/${id}/original` + (queryParams ? `?${queryParams}` : ''), filename);
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.error_downloading', { values: { filename } }));
|
||||
@@ -411,10 +393,7 @@ export const getOwnedAssetsWithWarning = (assets: TimelineAsset[], user: UserRes
|
||||
const numberOfIssues = [...assets].filter((a) => user && a.ownerId !== user.id).length;
|
||||
if (numberOfIssues > 0) {
|
||||
const $t = get(t);
|
||||
notificationController.show({
|
||||
message: $t('errors.cant_change_metadata_assets_count', { values: { count: numberOfIssues } }),
|
||||
type: NotificationType.Warning,
|
||||
});
|
||||
toastManager.warning($t('errors.cant_change_metadata_assets_count', { values: { count: numberOfIssues } }));
|
||||
}
|
||||
return ids;
|
||||
};
|
||||
@@ -434,12 +413,16 @@ export const stackAssets = async (assets: { id: string }[], showNotification = t
|
||||
try {
|
||||
const stack = await createStack({ stackCreateDto: { assetIds: assets.map(({ id }) => id) } });
|
||||
if (showNotification) {
|
||||
notificationController.show({
|
||||
message: $t('stacked_assets_count', { values: { count: stack.assets.length } }),
|
||||
type: NotificationType.Info,
|
||||
button: {
|
||||
text: $t('view_stack'),
|
||||
onClick: () => navigate({ targetRoute: 'current', assetId: stack.primaryAssetId }),
|
||||
toastManager.custom({
|
||||
component: ToastAction,
|
||||
props: {
|
||||
title: $t('success'),
|
||||
description: $t('stacked_assets_count', { values: { count: stack.assets.length } }),
|
||||
color: 'success',
|
||||
button: {
|
||||
text: $t('view_stack'),
|
||||
onClick: () => navigate({ targetRoute: 'current', assetId: stack.primaryAssetId }),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -468,10 +451,7 @@ export const deleteStack = async (stackIds: string[]) => {
|
||||
|
||||
await deleteStacks({ bulkIdsDto: { ids: [...ids] } });
|
||||
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: $t('unstacked_assets_count', { values: { count } }),
|
||||
});
|
||||
toastManager.success($t('unstacked_assets_count', { values: { count } }));
|
||||
|
||||
const assets = stacks.flatMap((stack) => stack.assets);
|
||||
for (const asset of assets) {
|
||||
@@ -492,10 +472,7 @@ export const keepThisDeleteOthers = async (keepAsset: AssetResponseDto, stack: S
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: assetsToDeleteIds } });
|
||||
await deleteStacks({ bulkIdsDto: { ids: [stack.id] } });
|
||||
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: $t('kept_this_deleted_others', { values: { count: assetsToDeleteIds.length } }),
|
||||
});
|
||||
toastManager.success($t('kept_this_deleted_others', { values: { count: assetsToDeleteIds.length } }));
|
||||
|
||||
keepAsset.stack = null;
|
||||
return keepAsset;
|
||||
@@ -548,11 +525,7 @@ export const toggleArchive = async (asset: AssetResponseDto) => {
|
||||
});
|
||||
|
||||
asset.isArchived = data.isArchived;
|
||||
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: asset.isArchived ? $t(`added_to_archive`) : $t(`removed_from_archive`),
|
||||
});
|
||||
toastManager.success(asset.isArchived ? $t(`added_to_archive`) : $t(`removed_from_archive`));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_add_remove_archive', { values: { archived: asset.isArchived } }));
|
||||
}
|
||||
@@ -571,13 +544,11 @@ export const archiveAssets = async (assets: { id: string }[], visibility: AssetV
|
||||
});
|
||||
}
|
||||
|
||||
notificationController.show({
|
||||
message:
|
||||
visibility === AssetVisibility.Archive
|
||||
? $t('archived_count', { values: { count: ids.length } })
|
||||
: $t('unarchived_count', { values: { count: ids.length } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
toastManager.success(
|
||||
visibility === AssetVisibility.Archive
|
||||
? $t('archived_count', { values: { count: ids.length } })
|
||||
: $t('unarchived_count', { values: { count: ids.length } }),
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(
|
||||
error,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { isHttpError } from '@immich/sdk';
|
||||
import { notificationController, NotificationType } from '../components/shared-components/notification/notification';
|
||||
import { toastManager } from '@immich/ui';
|
||||
|
||||
export function getServerErrorMessage(error: unknown) {
|
||||
if (!isHttpError(error)) {
|
||||
@@ -34,7 +34,7 @@ export function handleError(error: unknown, message: string) {
|
||||
|
||||
const errorMessage = serverMessage || message;
|
||||
|
||||
notificationController.show({ message: errorMessage, type: NotificationType.Error });
|
||||
toastManager.danger(errorMessage);
|
||||
|
||||
return errorMessage;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user