Pacien B 2025-12-17 22:32:59 +05:30 committed by GitHub
commit 54b98035a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 68 additions and 1 deletions

View File

@ -974,6 +974,7 @@
"error_downloading": "Error downloading {filename}",
"error_hiding_buy_button": "Error hiding buy button",
"error_removing_assets_from_album": "Error removing assets from album, check console for more details",
"error_removing_tag_from_assets": "Error removing tag from assets, check console for more details",
"error_selecting_all_assets": "Error selecting all assets",
"exclusion_pattern_already_exists": "This exclusion pattern already exists.",
"failed_to_create_album": "Failed to create album",
@ -1717,6 +1718,7 @@
"remove_memory": "Remove memory",
"remove_photo_from_memory": "Remove photo from this memory",
"remove_tag": "Remove tag",
"remove_tag_from_assets_confirmation": "Are you sure you want to remove this tag from {count, plural, one {# asset} other {# assets}}?",
"remove_url": "Remove URL",
"remove_user": "Remove user",
"removed_api_key": "Removed API Key: {name}",

View File

@ -0,0 +1,60 @@
<script lang="ts">
import { getAssetControlContext } from '$lib/components/timeline/AssetSelectControlBar.svelte';
import { handleError } from '$lib/utils/handle-error';
import { removeTag } from '$lib/utils/asset-utils';
import { IconButton, modalManager, toastManager } from '@immich/ui';
import { mdiTagRemoveOutline, mdiTagRemove } from '@mdi/js';
import { t } from 'svelte-i18n';
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
interface Props {
tagId: string;
onRemove: ((assetIds: string[]) => void) | undefined;
menuItem?: boolean;
}
let { tagId, onRemove, menuItem = false }: Props = $props();
const { getAssets, clearSelect } = getAssetControlContext();
const removeTagFromAssets = async () => {
const assets = getAssets();
const isConfirmed = await modalManager.showDialog({
prompt: $t('remove_tag_from_assets_confirmation', { values: { count: assets.length } }),
});
if (!isConfirmed) {
return;
}
try {
const assetIds = [...assets].map((a) => a.id);
await removeTag({
assetIds,
tagIds: [tagId],
showNotification: true,
});
// Clear selection and trigger timeline refresh
onRemove?.(assetIds);
clearSelect();
} catch (error) {
handleError(error, $t('errors.error_removing_tag_from_assets'));
}
};
</script>
{#if menuItem}
<MenuOption text={$t('remove_tag')} icon={mdiTagRemoveOutline} onClick={removeTagFromAssets} />
{:else}
<IconButton
shape="round"
color="secondary"
variant="ghost"
aria-label={$t('remove_tag')}
icon={mdiTagRemove}
onclick={removeTagFromAssets}
/>
{/if}

View File

@ -19,6 +19,7 @@
import { t } from 'svelte-i18n';
import type { PageData } from './$types';
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import RemoveTagAction from '$lib/components/timeline/actions/RemoveTagAction.svelte';
import AddToAlbum from '$lib/components/timeline/actions/AddToAlbumAction.svelte';
import ArchiveAction from '$lib/components/timeline/actions/ArchiveAction.svelte';
import ChangeDate from '$lib/components/timeline/actions/ChangeDateAction.svelte';
@ -169,7 +170,11 @@
<FavoriteAction
removeFavorite={assetInteraction.isAllFavorite}
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
></FavoriteAction>
/>
<RemoveTagAction
tagId={tag.id}
onRemove={(assetIds) => timelineManager.removeAssets(assetIds)}
/>
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
<DownloadAction menuItem />
<ChangeDate menuItem />