|
| 1 | +# Architecture |
| 2 | + |
| 3 | +## Project Structure |
| 4 | + |
| 5 | +``` |
| 6 | +src/ |
| 7 | +├── pages/ |
| 8 | +│ └── Editor.tsx # Main layout (sidebar + editor) |
| 9 | +├── components/ |
| 10 | +│ ├── FileSystemAdapters/FileSystem/ |
| 11 | +│ │ ├── LocalFileSystem.tsx # File operations orchestrator |
| 12 | +│ │ ├── FileSystemItem.tsx # Recursive folder tree renderer |
| 13 | +│ │ ├── RightClickMenu.tsx # Context menu UI |
| 14 | +│ │ ├── WorkspaceSelector.tsx # Initial folder picker |
| 15 | +│ │ └── GettingStartedHelper.tsx |
| 16 | +│ ├── MarkdownEditor/ |
| 17 | +│ │ ├── RemirrorComponent.tsx # Editor instance |
| 18 | +│ │ ├── FileEditor.tsx # File content manager |
| 19 | +│ │ ├── RemirrorMarkdownToolbar.tsx |
| 20 | +│ │ └── RemirrorMarkdownEditor.tsx |
| 21 | +│ └── ui/ # Button, ResizableSidebar, etc. |
| 22 | +└── models/ |
| 23 | + └── DirectoryNode.ts # Core file tree model |
| 24 | +``` |
| 25 | + |
| 26 | +## Data Flow |
| 27 | + |
| 28 | +### File Tree Management |
| 29 | +- `DirectoryNode` — Wraps `FileSystemFileHandle` and `FileSystemDirectoryHandle` from the browser API |
| 30 | +- Maintains parent-child relationships and tracks unsaved changes |
| 31 | +- Methods: `createFile()`, `createFolder()`, `delete()`, `renameFile()`, `moveNodeToNewParent()` |
| 32 | + |
| 33 | +### Editor State |
| 34 | +1. `Editor.tsx` holds `selectedFile` and `selectedDirectory` state |
| 35 | +2. `LocalFileSystem` orchestrates file operations (CRUD, rename, move) |
| 36 | +3. `FileEditor` loads/saves markdown content via `DirectoryNode.loadFileContent()` and `saveFileContent()` |
| 37 | +4. `FileSystemItem` recursively renders the file tree with drag-and-drop |
| 38 | + |
| 39 | +### Rendering Flow |
| 40 | +``` |
| 41 | +Editor.tsx (state) |
| 42 | +├── WorkspaceSelector (initial folder pick) |
| 43 | +├── ResizableSidebar |
| 44 | +│ └── LocalFileSystem |
| 45 | +│ └── FileSystemItem (recursive tree) |
| 46 | +└── FileEditor |
| 47 | + └── RemirrorComponent (markdown editor) |
| 48 | +``` |
| 49 | + |
| 50 | +## Key Patterns |
| 51 | + |
| 52 | +### Force Rerender Counter |
| 53 | +File operations mutate `DirectoryNode` objects directly (to avoid expensive re-creates). A `forceRerenderCounter` is incremented after mutations and passed as the React key to force tree re-renders. |
| 54 | + |
| 55 | +### Conflict Handling |
| 56 | +When creating files/folders with duplicate names, the app appends `(1)`, `(2)`, etc.: `Untitled.md` → `Untitled (1).md` |
| 57 | + |
| 58 | +### Image Blob URLs |
| 59 | +Images are loaded as blob URLs for display, then converted back to relative paths on save. Mapping stored in `DirectoryNode.replacedImages`. |
| 60 | + |
| 61 | +### Drag & Drop |
| 62 | +Implemented via React DOM events on `FileSystemItem`. Drops trigger `moveNodeToNewParent()` which uses the browser API to move files. |
| 63 | + |
| 64 | +## Limitations |
| 65 | + |
| 66 | +- **Browser-only**: No Node.js filesystem access (security restriction) |
| 67 | +- **Single directory scope**: Can only access one folder at a time (File System Access API constraint) |
| 68 | +- **Image handling**: Images must be in the same folder hierarchy as the notes |
| 69 | +- **No sync**: No built-in backup or sync to cloud |
0 commit comments