返回 oh-my-ppt
PageTitleEditDialog.tsx
根目录 / src / renderer / src / components / session-detail / modal / PageTitleEditDialog.tsx
1 import { useT } from '@renderer/i18n'
2 import { ipc } from '@renderer/lib/ipc'
3 import { useGenerateStore, useSessionDetailUiStore, useToastStore } from '@renderer/store'
4 import { Button } from '../../ui/Button'
5 import { Input } from '../../ui/Input'
6 import { normalizePagesForSelection } from '../shared/pageUtils'
7 import {
8 Dialog,
9 DialogContent,
10 DialogDescription,
11 DialogFooter,
12 DialogHeader,
13 DialogTitle
14 } from '../../ui/Dialog'
15
16 interface PageTitleEditDialogProps {
17 sessionId: string
18 }
19
20 export function PageTitleEditDialog({ sessionId }: PageTitleEditDialogProps): React.JSX.Element {
21 const t = useT()
22 const pageId = useSessionDetailUiStore((state) => state.pageTitleEditPageId)
23 const value = useSessionDetailUiStore((state) => state.pageTitleEditDraft)
24 const isManagingPages = useSessionDetailUiStore((state) => state.isManagingPages)
25 const currentPages = useGenerateStore((state) => state.currentPages)
26 const setValue = useSessionDetailUiStore((state) => state.setPageTitleEditDraft)
27 const close = useSessionDetailUiStore((state) => state.closePageTitleEdit)
28 const toastError = useToastStore((state) => state.error)
29 const open = Boolean(pageId)
30
31 const handleOpenChange = (nextOpen: boolean): void => {
32 if (!nextOpen && !isManagingPages) close()
33 }
34
35 const handleSave = async (): Promise<void> => {
36 if (!sessionId || !pageId) return
37 const title = value.replace(/\s+/g, ' ').trim()
38 if (!title) {
39 toastError(t('pageManagement.pageTitleRequired'))
40 return
41 }
42 const page = normalizePagesForSelection(currentPages).find((item) => item.id === pageId)
43 if (page && title === page.title) {
44 close()
45 return
46 }
47 useSessionDetailUiStore.getState().setIsManagingPages(true)
48 try {
49 const result = await ipc.updateSessionPageTitle({
50 sessionId,
51 pageId,
52 title
53 })
54 useGenerateStore.getState().setPages(result.generatedPages)
55 useSessionDetailUiStore.getState().setSelectedPageId(result.selectedPageId || pageId)
56 useSessionDetailUiStore.getState().bumpPreviewKey()
57 close()
58 } catch (error) {
59 toastError(error instanceof Error ? error.message : t('pageManagement.updateTitleFailed'))
60 } finally {
61 useSessionDetailUiStore.getState().setIsManagingPages(false)
62 }
63 }
64
65 return (
66 <Dialog open={open} onOpenChange={handleOpenChange}>
67 <DialogContent showClose={!isManagingPages}>
68 <DialogHeader>
69 <DialogTitle>{t('pageManagement.editPageTitle')}</DialogTitle>
70 <DialogDescription>{t('pageManagement.editPageTitleDescription')}</DialogDescription>
71 </DialogHeader>
72 <div className="space-y-2">
73 <label className="text-xs font-medium text-[#5d6b4d]" htmlFor="page-title-input">
74 {t('pageManagement.pageTitleLabel')}
75 </label>
76 <Input
77 id="page-title-input"
78 value={value}
79 onChange={(event) => setValue(event.target.value)}
80 onKeyDown={(event) => {
81 if (event.key === 'Enter') {
82 event.preventDefault()
83 void handleSave()
84 }
85 }}
86 placeholder={t('pageManagement.pageTitlePlaceholder')}
87 disabled={isManagingPages}
88 autoFocus
89 />
90 </div>
91 <DialogFooter>
92 <Button
93 type="button"
94 variant="outline"
95 size="sm"
96 onClick={() => handleOpenChange(false)}
97 disabled={isManagingPages}
98 >
99 {t('common.cancel')}
100 </Button>
101 <Button
102 type="button"
103 size="sm"
104 onClick={() => void handleSave()}
105 disabled={isManagingPages || !value.trim()}
106 >
107 {t('pageManagement.savePageTitle')}
108 </Button>
109 </DialogFooter>
110 </DialogContent>
111 </Dialog>
112 )
113 }
114
114 lines Plain Text