import Wrapper from '@/components/ui/Wrapper'; import { useFileSystem } from '@/hooks/useFilesystem'; import { CoreBridge, PlaceholderBridge, RichText, TenTapStartKit, Toolbar, useEditorBridge, useEditorContent } from '@10play/tentap-editor'; import { useRoute } from '@react-navigation/native'; import { format } from 'date-fns'; import { StorageAccessFramework } from 'expo-file-system'; import { useRouter } from 'expo-router'; import { marked } from 'marked'; import React, { useEffect, useState } from 'react'; import { Keyboard, View } from 'react-native'; import { Appbar, Button, Dialog, Menu, Portal, Text, useTheme } from 'react-native-paper'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import turndown from 'turndown-rn'; export default function EditorScreen() { const [entryText, setEntryText] = useState(''); const [stats, setStats] = useState<{ words: number; characters: number }>({ words: 0, characters: 0, }); useEffect(() => { const words = entryText.trim().split(/\s+/).filter(Boolean).length; const characters = entryText.length; setStats({ words, characters }); } , [entryText]); const navigation = useRouter(); const route = useRoute(); const { writeFile, deleteFile } = useFileSystem(); const { fileUri, fileDatetime } = route.params as { fileUri: string | undefined, fileDatetime: Date } || { fileUri: undefined, fileDatetime: new Date() }; const [loadedContents, setLoadedContents] = useState(""); const [menuVisible, setMenuVisible] = useState(false); const [dialogVisible, setDialogVisible] = useState(false); const openMenu = () => { setMenuVisible(true); }; const closeMenu = () => { setMenuVisible(false); }; const openDialog = () => { setDialogVisible(true); }; const closeDialog = () => { setDialogVisible(false); }; const loadFileContent = async (fileUri: string, forceReload = false) => { try { // Replace with your actual file reading logic const content = await StorageAccessFramework.readAsStringAsync(fileUri); setLoadedContents(await marked.parse(content)); return (await marked.parse(content)); } catch (error) { console.error('Error loading file content:', error); } }; const saveFileContent = async () => { console.log("Begin Save"); // try{ // } // catch (error) { // console.error("Error creating file:", error); // return; // } try { if (!content.html) return; // Convert HTML back to markdown const turndownService = new turndown({ headingStyle: 'atx', hr: '---', bulletListMarker: '-', codeBlockStyle: 'fenced', fence: '```', emDelimiter: '*', strongDelimiter: '**', linkStyle: 'inlined', linkReferenceStyle: 'full', }); // Optional: Add custom rules for better conversion turndownService.addRule('strikethrough', { filter: ['del', 's'], replacement: (content: string) => `~~${content}~~` }); turndownService.addRule('underline', { filter: ['u', 'ins'], replacement: (content: string) => `${content}` }); const markdownContent = turndownService.turndown(content.html); if (markdownContent == turndownService.turndown(loadedContents)) { console.log("Skipping..."); return; } // Save the markdown content await writeFile(fileUri ?? format(fileDatetime, 't'), markdownContent); console.log(`${fileDatetime} saved successfully`); } catch (error) { console.error(`Error saving ${fileUri}:`, error); } }; useEffect(() => { if (fileUri) { loadFileContent(fileUri); } }, [fileUri]); useEffect(() => { editor.setContent(loadedContents); }, [loadedContents]); const theme = useTheme(); const entryDate = format(fileDatetime, 'LLL d, h:mm aaa'); const insets = useSafeAreaInsets(); const [keyboardHeight, setKeyboardHeight] = useState(0); useEffect(() => { const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => { setKeyboardHeight(Keyboard.metrics()?.height || 0); }); const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => { setKeyboardHeight(0); }); return () => { keyboardDidShowListener.remove(); keyboardDidHideListener.remove(); }; }, []); const editor = useEditorBridge({ autofocus: true, avoidIosKeyboard: true, theme: { webviewContainer: { paddingLeft: 15, backgroundColor: theme.colors.surface, }, }, bridgeExtensions: [ ...TenTapStartKit, CoreBridge.configureCSS(` * { font-size: 14px; } `), PlaceholderBridge.configureExtension({ placeholder: '', }), ], initialContent: loadedContents, }); const content = { html: useEditorContent(editor, { type: 'html' }), text: useEditorContent(editor, { type: 'text' }), }; useEffect(() => { content.text && setEntryText(content.text ?? 'Nothing loaded.'); }, [content]); return ( { content.text && content.text != loadedContents ? { saveFileContent(); navigation.back(); }} /> : { navigation.back(); }} /> } { }} /> { }} /> { openMenu(); }} />}> { navigation.back(); closeMenu(); }} title="Cancel" /> { openDialog(); closeMenu(); }} title="Delete" /> Delete file? Entry for {' '} {format(fileDatetime, "MMM dd, yyyy, HH:mm:ss")} will be permanently deleted. {/* */} {/* */} ); };