fix: import markdown via input dynamique (pas d'input caché dans le DOM)
Some checks failed
CI / Lint, Unit Tests & Build (push) Successful in 5m37s
CI / Deploy production (on server) (push) Failing after 18s

L'input caché dans le toolbar était bloqué par le conteneur parent.
Maintenant l'input est créé dynamiquement dans le handler et détruit
après usage — garanti d'ouvrir l'explorateur fichiers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Antigravity
2026-05-29 13:44:31 +00:00
parent 435de0a30c
commit aff8e688a5

View File

@@ -45,7 +45,6 @@ export function NoteEditorToolbar({ mode, onClose, onToggleAttachments, attachme
const [isConverting, setIsConverting] = useState(false) const [isConverting, setIsConverting] = useState(false)
const [shareOpen, setShareOpen] = useState(false) const [shareOpen, setShareOpen] = useState(false)
const [flashcardsOpen, setFlashcardsOpen] = useState(false) const [flashcardsOpen, setFlashcardsOpen] = useState(false)
const mdImportInputRef = useRef<HTMLInputElement>(null)
const notebookName = notebooks.find(nb => nb.id === note.notebookId)?.name || null const notebookName = notebooks.find(nb => nb.id === note.notebookId)?.name || null
@@ -79,29 +78,31 @@ export function NoteEditorToolbar({ mode, onClose, onToggleAttachments, attachme
} }
// ── Markdown import ─────────────────────────────────────────────────────── // ── Markdown import ───────────────────────────────────────────────────────
const handleImportMarkdownFile = (e: React.ChangeEvent<HTMLInputElement>) => { const openMarkdownImport = () => {
const file = e.target.files?.[0] const input = document.createElement('input')
if (!file) return input.type = 'file'
const reader = new FileReader() input.accept = '.md,text/markdown'
reader.onload = (ev) => { input.onchange = (e) => {
try { const file = (e.target as HTMLInputElement).files?.[0]
const md = ev.target?.result as string if (!file) return
const html = markdownToHTML(md) const reader = new FileReader()
const extractedTitle = extractMarkdownTitle(md) reader.onload = (ev) => {
const editor = richTextEditorRef?.current?.getEditor() try {
if (editor) { const md = ev.target?.result as string
editor.commands.setContent(html) const html = markdownToHTML(md)
const extractedTitle = extractMarkdownTitle(md)
const editor = richTextEditorRef?.current?.getEditor()
if (editor) editor.commands.setContent(html)
actions.setContent(html)
if (extractedTitle) actions.setTitle(extractedTitle)
toast.success(t('richTextEditor.markdownImportSuccess'))
} catch {
toast.error(t('richTextEditor.markdownExportError'))
} }
actions.setContent(html)
if (extractedTitle) actions.setTitle(extractedTitle)
toast.success(t('richTextEditor.markdownImportSuccess'))
} catch {
toast.error(t('richTextEditor.markdownExportError'))
} }
reader.readAsText(file)
} }
reader.readAsText(file) input.click()
// Reset input so same file can be imported again
e.target.value = ''
} }
const handleConvertToRichtext = async () => { const handleConvertToRichtext = async () => {
@@ -301,7 +302,7 @@ export function NoteEditorToolbar({ mode, onClose, onToggleAttachments, attachme
<FileDown className="h-4 w-4 me-2" /> <FileDown className="h-4 w-4 me-2" />
{t('richTextEditor.exportMarkdown')} {t('richTextEditor.exportMarkdown')}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={() => setTimeout(() => mdImportInputRef.current?.click(), 0)}> <DropdownMenuItem onClick={openMarkdownImport}>
<FileUp className="h-4 w-4 me-2" /> <FileUp className="h-4 w-4 me-2" />
{t('richTextEditor.importMarkdown')} {t('richTextEditor.importMarkdown')}
</DropdownMenuItem> </DropdownMenuItem>
@@ -498,14 +499,7 @@ export function NoteEditorToolbar({ mode, onClose, onToggleAttachments, attachme
)} )}
</div> </div>
</div> </div>
{/* Hidden file input for Markdown import */} {/* Hidden file input for Markdown import — remplacé par création dynamique dans openMarkdownImport */}
<input
ref={mdImportInputRef}
type="file"
accept=".md,text/markdown"
className="hidden"
onChange={handleImportMarkdownFile}
/>
</> </>
) )
} }