{
+
);
};
diff --git a/packages/frontend/core/src/components/page-list/operation-cell.tsx b/packages/frontend/core/src/components/page-list/operation-cell.tsx
index 9fd9328c66..9c546ed40c 100644
--- a/packages/frontend/core/src/components/page-list/operation-cell.tsx
+++ b/packages/frontend/core/src/components/page-list/operation-cell.tsx
@@ -4,7 +4,6 @@ import {
Menu,
MenuIcon,
MenuItem,
- toast,
Tooltip,
} from '@affine/component';
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
@@ -334,8 +333,7 @@ export const TagOperationCell = ({
const handleDelete = useCallback(() => {
onTagDelete([tag.id]);
- toast(t['com.affine.tags.delete-tags.toast']());
- }, [onTagDelete, t, tag.id]);
+ }, [onTagDelete, tag.id]);
return (
<>
diff --git a/packages/frontend/core/src/components/page-list/tags/virtualized-tag-list.tsx b/packages/frontend/core/src/components/page-list/tags/virtualized-tag-list.tsx
index 6c7290f7f1..c44f9ab4e3 100644
--- a/packages/frontend/core/src/components/page-list/tags/virtualized-tag-list.tsx
+++ b/packages/frontend/core/src/components/page-list/tags/virtualized-tag-list.tsx
@@ -1,7 +1,5 @@
-import { toast } from '@affine/component';
import type { Tag } from '@affine/core/modules/tag';
import { Trans } from '@affine/i18n';
-import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useService } from '@toeverything/infra';
import { Workspace } from '@toeverything/infra';
import { useCallback, useMemo, useRef, useState } from 'react';
@@ -25,7 +23,6 @@ export const VirtualizedTagList = ({
tagMetas: TagMeta[];
onTagDelete: (tagIds: string[]) => void;
}) => {
- const t = useAFFiNEI18N();
const listRef = useRef(null);
const [showFloatingToolbar, setShowFloatingToolbar] = useState(false);
const [showCreateTagInput, setShowCreateTagInput] = useState(false);
@@ -74,10 +71,9 @@ export const VirtualizedTagList = ({
const handleDelete = useCallback(() => {
onTagDelete(selectedTagIds);
- toast(t['com.affine.delete-tags.count']({ count: selectedTagIds.length }));
hideFloatingToolbar();
return;
- }, [hideFloatingToolbar, onTagDelete, selectedTagIds, t]);
+ }, [hideFloatingToolbar, onTagDelete, selectedTagIds]);
const onOpenCreate = useCallback(() => {
setShowCreateTagInput(true);
diff --git a/packages/frontend/core/src/modules/tag/index.ts b/packages/frontend/core/src/modules/tag/index.ts
index a0fab4c382..c485f457b9 100644
--- a/packages/frontend/core/src/modules/tag/index.ts
+++ b/packages/frontend/core/src/modules/tag/index.ts
@@ -1,3 +1,4 @@
export { Tag } from './entities/tag';
export { tagColorMap } from './entities/utils';
export { TagService } from './service/tag';
+export { DeleteTagConfirmModal } from './view/delete-tag-modal';
diff --git a/packages/frontend/core/src/modules/tag/view/delete-tag-modal.tsx b/packages/frontend/core/src/modules/tag/view/delete-tag-modal.tsx
new file mode 100644
index 0000000000..9b3c3641a4
--- /dev/null
+++ b/packages/frontend/core/src/modules/tag/view/delete-tag-modal.tsx
@@ -0,0 +1,65 @@
+import { ConfirmModal, toast } from '@affine/component';
+import { Trans } from '@affine/i18n';
+import { useAFFiNEI18N } from '@affine/i18n/hooks';
+import { useLiveData, useService } from '@toeverything/infra';
+import { useCallback, useMemo } from 'react';
+
+import { TagService } from '../service/tag';
+
+export const DeleteTagConfirmModal = ({
+ open,
+ onOpenChange,
+ selectedTagIds,
+}: {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ selectedTagIds: string[];
+}) => {
+ const t = useAFFiNEI18N();
+ const tagService = useService(TagService);
+ const tags = useLiveData(tagService.tags);
+ const selectedTags = useMemo(() => {
+ return tags.filter(tag => selectedTagIds.includes(tag.id));
+ }, [selectedTagIds, tags]);
+ const tagName = useLiveData(selectedTags[0]?.value || '');
+
+ const handleDelete = useCallback(() => {
+ selectedTagIds.forEach(tagId => {
+ tagService.deleteTag(tagId);
+ });
+
+ toast(
+ selectedTagIds.length > 1
+ ? t['com.affine.delete-tags.count']({ count: selectedTagIds.length })
+ : t['com.affine.tags.delete-tags.toast']()
+ );
+
+ onOpenChange(false);
+ }, [onOpenChange, selectedTagIds, t, tagService]);
+
+ return (
+ }}
+ />
+ ) : (
+ t['com.affine.delete-tags.confirm.multi-tag-description']({
+ count: selectedTags.length.toString(),
+ })
+ )
+ }
+ confirmButtonOptions={{
+ type: 'warning',
+ children: t['Delete'](),
+ }}
+ onConfirm={handleDelete}
+ />
+ );
+};
diff --git a/packages/frontend/core/src/pages/workspace/all-tag/index.tsx b/packages/frontend/core/src/pages/workspace/all-tag/index.tsx
index 1c4c239e85..c1aa71c47a 100644
--- a/packages/frontend/core/src/pages/workspace/all-tag/index.tsx
+++ b/packages/frontend/core/src/pages/workspace/all-tag/index.tsx
@@ -4,7 +4,7 @@ import {
} from '@affine/core/components/page-list/tags';
import { CreateOrEditTag } from '@affine/core/components/page-list/tags/create-tag';
import type { TagMeta } from '@affine/core/components/page-list/types';
-import { TagService } from '@affine/core/modules/tag';
+import { DeleteTagConfirmModal, TagService } from '@affine/core/modules/tag';
import { useLiveData, useService } from '@toeverything/infra';
import { useCallback, useState } from 'react';
@@ -33,16 +33,25 @@ const EmptyTagListHeader = () => {
export const AllTag = () => {
const tagService = useService(TagService);
const tags = useLiveData(tagService.tags);
+ const [open, setOpen] = useState(false);
+ const [selectedTagIds, setSelectedTagIds] = useState([]);
const tagMetas: TagMeta[] = useLiveData(tagService.tagMetas);
- const handleDelete = useCallback(
- (tagIds: string[]) => {
- tagIds.forEach(tagId => {
- tagService.deleteTag(tagId);
- });
+ const handleCloseModal = useCallback(
+ (open: boolean) => {
+ setOpen(open);
+ setSelectedTagIds([]);
},
- [tagService]
+ [setOpen]
+ );
+
+ const onTagDelete = useCallback(
+ (tagIds: string[]) => {
+ setOpen(true);
+ setSelectedTagIds(tagIds);
+ },
+ [setOpen, setSelectedTagIds]
);
return (
@@ -56,13 +65,18 @@ export const AllTag = () => {
) : (
} />
)}
+
>
);
};
diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json
index 45167f5c49..bc6406ceed 100644
--- a/packages/frontend/i18n/src/resources/en.json
+++ b/packages/frontend/i18n/src/resources/en.json
@@ -1165,6 +1165,9 @@
"com.affine.delete-tags.count": "{{count}} tag deleted",
"com.affine.delete-tags.count_one": "{{count}} tag deleted",
"com.affine.delete-tags.count_other": "{{count}} tags deleted",
+ "com.affine.delete-tags.confirm.title": "Delete Tag?",
+ "com.affine.delete-tags.confirm.description": "Deleting <1>{{tag}}1> cannot be undone, please proceed with caution.",
+ "com.affine.delete-tags.confirm.multi-tag-description": "Deleting {{count}} tags cannot be undone, please proceed with caution.",
"com.affine.workbench.split-view-menu.keep-this-one": "Solo View",
"com.affine.workbench.split-view.page-menu-open": "Open in split view",
"com.affine.search-tags.placeholder": "Type here ...",