/** * Main Application * Coordinates all modules and handles user interactions */ // Global state let webdavClient; let fileTree; let editor; let darkMode; let collectionSelector; let clipboard = null; let currentFilePath = null; // Simple event bus const eventBus = { listeners: {}, on(event, callback) { if (!this.listeners[event]) { this.listeners[event] = []; } this.listeners[event].push(callback); }, dispatch(event, data) { if (this.listeners[event]) { this.listeners[event].forEach(callback => callback(data)); } } }; window.eventBus = eventBus; // Initialize application document.addEventListener('DOMContentLoaded', async () => { // Initialize WebDAV client webdavClient = new WebDAVClient('/fs/'); // Initialize dark mode darkMode = new DarkMode(); document.getElementById('darkModeBtn').addEventListener('click', () => { darkMode.toggle(); }); // Initialize file tree fileTree = new FileTree('fileTree', webdavClient); fileTree.onFileSelect = async (item) => { await editor.loadFile(item.path); }; // Initialize collection selector collectionSelector = new CollectionSelector('collectionSelect', webdavClient); collectionSelector.onChange = async (collection) => { await fileTree.load(); }; await collectionSelector.load(); await fileTree.load(); // Initialize editor editor = new MarkdownEditor('editor', 'preview', 'filenameInput'); editor.setWebDAVClient(webdavClient); // Add test content to verify preview works setTimeout(() => { if (!editor.editor.getValue()) { editor.editor.setValue('# Welcome to Markdown Editor\n\nStart typing to see preview...\n'); editor.updatePreview(); } }, 200); // Setup editor drop handler const editorDropHandler = new EditorDropHandler( document.querySelector('.editor-container'), async (file) => { await handleEditorFileDrop(file); } ); // Setup button handlers document.getElementById('newBtn').addEventListener('click', () => { editor.newFile(); }); document.getElementById('saveBtn').addEventListener('click', async () => { await editor.save(); }); document.getElementById('deleteBtn').addEventListener('click', async () => { await editor.deleteFile(); }); // Setup context menu handlers setupContextMenuHandlers(); // Initialize mermaid mermaid.initialize({ startOnLoad: true, theme: darkMode.isDark ? 'dark' : 'default' }); // Initialize file tree actions manager window.fileTreeActions = new FileTreeActions(webdavClient, fileTree, editor); // Listen for file-saved event to reload file tree window.eventBus.on('file-saved', async (path) => { if (fileTree) { await fileTree.load(); fileTree.selectNode(path); } }); window.eventBus.on('file-deleted', async () => { if (fileTree) { await fileTree.load(); } }); }); // Listen for column resize events to refresh editor window.addEventListener('column-resize', () => { if (editor && editor.editor) { editor.editor.refresh(); } }); /** * File Operations */ /** * Context Menu Handlers */ function setupContextMenuHandlers() { const menu = document.getElementById('contextMenu'); menu.addEventListener('click', async (e) => { const item = e.target.closest('.context-menu-item'); if (!item) return; const action = item.dataset.action; const targetPath = menu.dataset.targetPath; const isDir = menu.dataset.targetIsDir === 'true'; hideContextMenu(); await window.fileTreeActions.execute(action, targetPath, isDir); }); } // All context actions are now handled by FileTreeActions, so this function is no longer needed. // async function handleContextAction(action, targetPath, isDir) { ... } function updatePasteVisibility() { const pasteItem = document.getElementById('pasteMenuItem'); if (pasteItem) { pasteItem.style.display = clipboard ? 'block' : 'none'; } } /** * Editor File Drop Handler */ async function handleEditorFileDrop(file) { try { // Get current file's directory let targetDir = ''; if (currentFilePath) { const parts = currentFilePath.split('/'); parts.pop(); // Remove filename targetDir = parts.join('/'); } // Upload file const uploadedPath = await fileTree.uploadFile(targetDir, file); // Insert markdown link at cursor const isImage = file.type.startsWith('image/'); const link = isImage ? `![${file.name}](/${webdavClient.currentCollection}/${uploadedPath})` : `[${file.name}](/${webdavClient.currentCollection}/${uploadedPath})`; editor.insertAtCursor(link); showNotification(`Uploaded and inserted link`, 'success'); } catch (error) { console.error('Failed to handle file drop:', error); showNotification('Failed to upload file', 'error'); } } // Make showContextMenu global window.showContextMenu = showContextMenu;