import { useState, useEffect, useCallback } from 'react'; import { Paper, Textarea, Group, Text, Stack, Button, Box, } from '@mantine/core'; import { useDebouncedValue } from '@mantine/hooks'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import rehypeSanitize from 'rehype-sanitize'; import { IconDeviceFloppy } from '@tabler/icons-react'; import { useAppStore } from '../../stores'; interface NoteEditorProps { onSave?: () => void; } type ViewMode = 'edit' | 'preview'; export function NoteEditor({ onSave }: NoteEditorProps) { const notes = useAppStore((state) => state.notes); const updateNotesContent = useAppStore((state) => state.updateNotesContent); const saveNotes = useAppStore((state) => state.saveNotes); const fetchNotes = useAppStore((state) => state.fetchNotes); const [content, setContent] = useState(''); const [saving, setSaving] = useState(false); const [lastSaved, setLastSaved] = useState(null); const [viewMode] = useState('edit'); // Initialize content from notes useEffect(() => { if (notes) { setContent(notes.content); } }, [notes]); // Fetch notes on mount useEffect(() => { fetchNotes(); }, [fetchNotes]); // Auto-save with 3 second debounce const [debouncedContent] = useDebouncedValue(content, 3000); useEffect(() => { if (debouncedContent !== undefined && notes && debouncedContent !== content) { handleSave(debouncedContent); } }, [debouncedContent]); const handleSave = useCallback( async (value: string) => { if (!notes) return; setSaving(true); try { updateNotesContent(value); await saveNotes(value); setLastSaved(new Date()); onSave?.(); } catch (error) { console.error('Failed to save note:', error); } finally { setSaving(false); } }, [notes, updateNotesContent, saveNotes, onSave] ); const formatLastSaved = () => { if (!lastSaved) return '未保存'; const now = new Date(); const diff = now.getTime() - lastSaved.getTime(); if (diff < 1000) return '刚刚保存'; if (diff < 60000) return `${Math.floor(diff / 1000)}秒前保存`; return lastSaved.toLocaleTimeString('zh-CN'); }; const handleManualSave = () => { if (content && notes) { handleSave(content); } }; return ( {/* Header */} 便签 {saving ? '保存中...' : formatLastSaved()} {/* Editor/Preview Area */} {viewMode === 'edit' && (