import React, { useCallback } from 'react' import { FolderOpen, Save, Moon, Sun, Info, Download, Upload } from '../Icons' import { getMetonaEditor, useEditorStore } from '../../stores/editorStore' import { backupRepository } from '../../db/backupRepository' import { showToast } from '../../lib/toast' import { logError } from '../../lib/errorHandler' import type { ThemeMode } from '../../types/settings' interface ToolbarProps { onOpen: () => void onSave: () => void themeMode: ThemeMode onCycleTheme: () => void onShowAbout: () => void isAutoSaving: boolean autoSaveEnabled: boolean onToggleAutoSave: () => void } const THEME_LABELS: Record = { light: '亮色', dark: '暗色', warm: '暖色', } /** * 应用顶层工具栏 — 文件操作、自动保存、主题循环、数据备份、关于。 * 编辑器格式化和模式切换由 MetonaEditor 内置工具栏处理。 */ export const Toolbar = React.memo(function Toolbar({ onOpen, onSave, themeMode, onCycleTheme, onShowAbout, isAutoSaving, autoSaveEnabled, onToggleAutoSave, }: ToolbarProps) { const nextLabel = THEME_LABELS[themeMode] ?? '主题' const zenMode = useEditorStore(s => s.zenMode) // v0.6.0: Zen 专注模式切换(MetonaEditor 内置能力) const handleToggleZen = useCallback(() => { const editor = getMetonaEditor() if (!editor) return editor.toggleZen() }, []) // v0.6.0: 数据备份导出(sqlark exportAll → JSON 文件) const handleExport = useCallback(async () => { if (!window.electronAPI) return const data = await backupRepository.exportAll() if (!data) return const result = await window.electronAPI.exportData(JSON.stringify(data, null, 2)) if (result.success) { showToast('备份已导出', 'success') } else if (!result.canceled) { showToast(`导出失败: ${result.error ?? '未知错误'}`, 'error') } }, []) // v0.6.0: 数据备份导入(JSON 文件 → sqlark importTable) const handleImport = useCallback(async () => { if (!window.electronAPI) return const result = await window.electronAPI.importData() if (!result.success) return if (result.canceled || !result.content) return try { const data = JSON.parse(result.content) as Record[]> const ok = await backupRepository.importAll(data) if (ok) { // 恢复后刷新页面 — 所有 store 从新数据库重新加载(loadFromDB 有 _loaded 守卫, // 且 settings/sidebar 也只在初始化时读取,直接重载页面最可靠) showToast('备份已恢复', 'success') setTimeout(() => window.location.reload(), 800) } else { showToast('恢复备份失败', 'error') } } catch (error) { logError('解析备份文件失败', error) showToast('备份文件格式无效', 'error') } }, []) return (