Skip to content

Commit 1e7f0fa

Browse files
flaviutpionxzh
andauthored
fix: do not render export dialog until needed (#178)
* Do not render export dialog until needed This helps avoid many unnecessary API requests to fetch the history until they are actually asked for. * style: lint --------- Co-authored-by: Pionxzh <[email protected]>
1 parent 54ece73 commit 1e7f0fa

File tree

1 file changed

+77
-65
lines changed

1 file changed

+77
-65
lines changed

packages/userscript/src/ui/ExportDialog.tsx

Lines changed: 77 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,13 @@ const ConversationSelect: FC<ConversationSelectProps> = ({
6767
)
6868
}
6969

70-
interface ExportDialogProps {
70+
type ExportSource = 'API' | 'Local'
71+
72+
interface DialogContentProps {
7173
format: string
72-
open: boolean
73-
onOpenChange: (value: boolean) => void
7474
}
7575

76-
type ExportSource = 'API' | 'Local'
77-
78-
export const ExportDialog: FC<ExportDialogProps> = ({ format, open, onOpenChange, children }) => {
76+
const DialogContent: FC<DialogContentProps> = ({ format }) => {
7977
const { t } = useTranslation()
8078
const { enableMeta, exportMetaList, exportOfficialJsonFormat } = useSettingContext()
8179
const metaList = useMemo(() => enableMeta ? exportMetaList : [], [enableMeta, exportMetaList])
@@ -217,6 +215,78 @@ export const ExportDialog: FC<ExportDialogProps> = ({ format, open, onOpenChange
217215
.finally(() => setLoading(false))
218216
}, [])
219217

218+
return (
219+
<>
220+
<Dialog.Title className="DialogTitle">{t('Export Dialog Title')}</Dialog.Title>
221+
<div className="flex items-center text-gray-600 dark:text-gray-300 flex justify-between border-b-[1px] pb-3 mb-3 dark:border-gray-700">
222+
{t('Export from official export file')} {'(conversations.json)'}&nbsp;
223+
{exportSource === 'API' && (
224+
<button className="btn relative btn-neutral" onClick={() => fileInputRef.current?.click()}>
225+
<IconUpload className="w-4 h-4 text-white" />
226+
</button>
227+
)}
228+
</div>
229+
<input
230+
type="file"
231+
accept="application/json"
232+
className="hidden"
233+
ref={fileInputRef}
234+
onChange={onUpload}
235+
/>
236+
{exportSource === 'API' && (
237+
<div className="flex items-center text-gray-600 dark:text-gray-300 flex justify-between mb-3">
238+
{t('Export from API')}
239+
</div>
240+
)}
241+
<ConversationSelect
242+
conversations={conversations}
243+
selected={selected}
244+
setSelected={setSelected}
245+
disabled={processing}
246+
loading={loading}
247+
error={error}
248+
/>
249+
<div className="flex mt-6" style={{ justifyContent: 'space-between' }}>
250+
<select className="Select" disabled={processing} value={exportType} onChange={e => setExportType(e.currentTarget.value)}>
251+
{exportAllOptions.map(({ label }) => (
252+
<option key={t(label)} value={label}>{label}</option>
253+
))}
254+
</select>
255+
<div className="flex flex-grow"></div>
256+
<button className="Button red" disabled={disabled || exportSource === 'Local'} onClick={deleteAll}>
257+
{t('Delete')}
258+
</button>
259+
<button className="Button green ml-4" disabled={disabled} onClick={exportAll}>
260+
{t('Export')}
261+
</button>
262+
</div>
263+
{processing && (
264+
<>
265+
<div className="mt-2 mb-1 justify-between flex">
266+
<span className="truncate mr-8">{progress.currentName}</span>
267+
<span>{`${progress.completed}/${progress.total}`}</span>
268+
</div>
269+
<div className="w-full bg-gray-200 rounded-full h-2.5 mb-4 dark:bg-gray-700">
270+
<div className="bg-blue-600 h-2.5 rounded-full" style={{ width: `${progress.completed / progress.total * 100}%` }} />
271+
</div>
272+
</>
273+
)}
274+
<Dialog.Close asChild>
275+
<button className="IconButton CloseButton" aria-label="Close">
276+
<IconCross />
277+
</button>
278+
</Dialog.Close>
279+
</>
280+
)
281+
}
282+
283+
interface ExportDialogProps {
284+
format: string
285+
open: boolean
286+
onOpenChange: (value: boolean) => void
287+
}
288+
289+
export const ExportDialog: FC<ExportDialogProps> = ({ format, open, onOpenChange, children }) => {
220290
return (
221291
<Dialog.Root
222292
open={open}
@@ -228,65 +298,7 @@ export const ExportDialog: FC<ExportDialogProps> = ({ format, open, onOpenChange
228298
<Dialog.Portal>
229299
<Dialog.Overlay className="DialogOverlay" />
230300
<Dialog.Content className="DialogContent">
231-
<Dialog.Title className="DialogTitle">{t('Export Dialog Title')}</Dialog.Title>
232-
<div className="flex items-center text-gray-600 dark:text-gray-300 flex justify-between border-b-[1px] pb-3 mb-3 dark:border-gray-700">
233-
{t('Export from official export file')} {'(conversations.json)'}&nbsp;
234-
{exportSource === 'API' && (
235-
<button className="btn relative btn-neutral" onClick={() => fileInputRef.current?.click()}>
236-
<IconUpload className="w-4 h-4 text-white" />
237-
</button>
238-
)}
239-
</div>
240-
<input
241-
type="file"
242-
accept="application/json"
243-
className="hidden"
244-
ref={fileInputRef}
245-
onChange={onUpload}
246-
/>
247-
{exportSource === 'API' && (
248-
<div className="flex items-center text-gray-600 dark:text-gray-300 flex justify-between mb-3">
249-
{t('Export from API')}
250-
</div>
251-
)}
252-
<ConversationSelect
253-
conversations={conversations}
254-
selected={selected}
255-
setSelected={setSelected}
256-
disabled={processing}
257-
loading={loading}
258-
error={error}
259-
/>
260-
<div className="flex mt-6" style={{ justifyContent: 'space-between' }}>
261-
<select className="Select" disabled={processing} value={exportType} onChange={e => setExportType(e.currentTarget.value)}>
262-
{exportAllOptions.map(({ label }) => (
263-
<option key={t(label)} value={label}>{label}</option>
264-
))}
265-
</select>
266-
<div className="flex flex-grow"></div>
267-
<button className="Button red" disabled={disabled || exportSource === 'Local'} onClick={deleteAll}>
268-
{t('Delete')}
269-
</button>
270-
<button className="Button green ml-4" disabled={disabled} onClick={exportAll}>
271-
{t('Export')}
272-
</button>
273-
</div>
274-
{processing && (
275-
<>
276-
<div className="mt-2 mb-1 justify-between flex">
277-
<span className="truncate mr-8">{progress.currentName}</span>
278-
<span>{`${progress.completed}/${progress.total}`}</span>
279-
</div>
280-
<div className="w-full bg-gray-200 rounded-full h-2.5 mb-4 dark:bg-gray-700">
281-
<div className="bg-blue-600 h-2.5 rounded-full" style={{ width: `${progress.completed / progress.total * 100}%` }} />
282-
</div>
283-
</>
284-
)}
285-
<Dialog.Close asChild>
286-
<button className="IconButton CloseButton" aria-label="Close">
287-
<IconCross />
288-
</button>
289-
</Dialog.Close>
301+
{open && <DialogContent format={format} />}
290302
</Dialog.Content>
291303
</Dialog.Portal>
292304
</Dialog.Root>

0 commit comments

Comments
 (0)