mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
b4b1205ee9
* ♻️ refactor(modal): migrate confirm modals to @lobehub/ui/base-ui Replace all `App.useApp().modal.confirm`, `Modal.confirm` and `AntModal.confirm` call sites with the headless `confirmModal` from `@lobehub/ui/base-ui`, dropping antd-only props (`centered`, `type`, `width`, `okButtonProps.type='primary'`, `okButtonProps.loading`, `classNames.root`) that the base-ui imperative API does not accept. - 82 files touched; `modal.confirm`/`Modal.confirm` call sites now zero - `PageEditor/store/action.ts`: drop `modal` arg from `handleDelete` - `ResourceManager/useUploadFolder`: replace dynamic `import('antd').Modal` - `Eval/DatasetsTab`: migrate `modal.success` to `confirmModal` Part of LOBE-9645 Phase 1. * ♻️ refactor(ui): migrate select/modal call sites to @lobehub/ui/base-ui - Convert imperative-modal factories (createXxxModal + Content split) for apikey, creds (Create/Edit/View), provider (CreateNewProvider), and messenger LinkModal. - Switch Select usages to base-ui Select (Messenger AgentSelect, provider sdkType). - Restructure CreateNewProvider form to vertical layout with manual section titles for tighter spacing; drop FormModal/Form group nesting. - Standardize small ActionIcon sizing via DESKTOP_HEADER_ICON_SMALL_SIZE (WideScreenButton, ToggleRightPanelButton, ContextDropdown, AddNewProvider). - Fix missing title on ResourceManager delete confirm modal so the header (title + close X) renders. - Update react skill and AGENTS.md to require base-ui priority over root @lobehub/ui / antd; expand component table and Common Mistakes with explicit base-ui rules. * ♻️ refactor(ui): swap antd Select to base-ui Select and migrate createStyles to createStaticStyles * ✅ test: update test mocks for base-ui confirmModal migration * ✅ test(e2e): switch delete confirm selector to base-ui dialog role
104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { type MenuProps } from '@lobehub/ui';
|
|
import { Icon } from '@lobehub/ui';
|
|
import { confirmModal } from '@lobehub/ui/base-ui';
|
|
import { PencilLineIcon, Trash } from 'lucide-react';
|
|
import { useCallback } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import { type RecentItem } from '@/server/routers/lambda/recent';
|
|
import { documentService } from '@/services/document';
|
|
import { taskService } from '@/services/task';
|
|
import { topicService } from '@/services/topic';
|
|
import { useHomeStore } from '@/store/home';
|
|
|
|
export const useRecentItemDropdownMenu = (
|
|
item: RecentItem,
|
|
toggleEditing: (visible?: boolean) => void,
|
|
) => {
|
|
const { t } = useTranslation(['common', 'topic', 'components']);
|
|
const [updateRecentTitle, refreshRecents] = useHomeStore((s) => [
|
|
s.updateRecentTitle,
|
|
s.refreshRecents,
|
|
]);
|
|
|
|
const handleRename = useCallback(
|
|
async (newTitle: string) => {
|
|
// Optimistic update
|
|
updateRecentTitle(item.id, newTitle);
|
|
|
|
// Persist to server
|
|
switch (item.type) {
|
|
case 'document': {
|
|
await documentService.updateDocument({ id: item.id, title: newTitle });
|
|
break;
|
|
}
|
|
case 'task': {
|
|
await taskService.update(item.id, { name: newTitle });
|
|
break;
|
|
}
|
|
case 'topic': {
|
|
await topicService.updateTopic(item.id, { title: newTitle });
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
[item, updateRecentTitle],
|
|
);
|
|
|
|
const handleDelete = useCallback(() => {
|
|
const confirmMessages: Record<string, string> = {
|
|
document: t('FileManager.actions.confirmDelete', { ns: 'components' }),
|
|
topic: t('actions.confirmRemoveTopic', { ns: 'topic' }),
|
|
};
|
|
|
|
confirmModal({
|
|
okButtonProps: { danger: true },
|
|
onOk: async () => {
|
|
switch (item.type) {
|
|
case 'topic': {
|
|
// Home has no active agent/group, so chatStore.removeTopic early-returns; call the service directly
|
|
await topicService.removeTopic(item.id);
|
|
break;
|
|
}
|
|
case 'document': {
|
|
await documentService.deleteDocument(item.id);
|
|
break;
|
|
}
|
|
case 'task': {
|
|
await taskService.delete(item.id);
|
|
break;
|
|
}
|
|
}
|
|
await refreshRecents();
|
|
},
|
|
title: confirmMessages[item.type] || t('delete', { ns: 'common' }),
|
|
});
|
|
}, [item, t, refreshRecents]);
|
|
|
|
const dropdownMenu = useCallback((): MenuProps['items'] => {
|
|
const canRename = true;
|
|
|
|
return [
|
|
...(canRename
|
|
? [
|
|
{
|
|
icon: <Icon icon={PencilLineIcon} />,
|
|
key: 'rename',
|
|
label: t('rename'),
|
|
onClick: () => toggleEditing(true),
|
|
},
|
|
]
|
|
: []),
|
|
{
|
|
danger: true,
|
|
icon: <Icon icon={Trash} />,
|
|
key: 'delete',
|
|
label: t('delete'),
|
|
onClick: handleDelete,
|
|
},
|
|
];
|
|
}, [item.type, t, toggleEditing, handleDelete]);
|
|
|
|
return { dropdownMenu, handleRename };
|
|
};
|