Current markdown file viewing requires toggling between "read" mode and "source text" mode, causing disorienting context loss. When editing a file, the view switches modes and scrolls to a different position.
Implement a live preview mode that displays rendered markdown while allowing inline editing, similar to Obsidian's live preview feature.
In FileViewer.tsx, there are two mutually exclusive modes:
| Mode | Markdown Preview | Monaco Editor |
|---|---|---|
preview |
Visible | Invisible |
source |
Invisible | Visible |
The toggle at line 776-779 switches between these two modes.
| Mode | Markdown Preview | Monaco Editor | Use Case |
|---|---|---|---|
preview |
Visible | Invisible | Reading |
source |
Invisible | Visible (normal) | Pure editing |
livePreview |
Visible | Visible (transparent bg) | Inline editing while reading |
State management (lines 237-242):
type ViewMode = 'preview' | 'source' | 'livePreview'
const previewModes = useRef(new Map<string, ViewMode>())Editor styling for live preview:
- Monaco editor needs transparent background
- Editor text matches markdown styling
Click handling in live preview:
- Map click coordinates to cursor position in Monaco
- Pass clicks through to editor for editing
Add third toggle state:
- Cycle button: Preview → LivePreview → Source → Preview
- Or two toggles: "Preview" + "Live Preview"
Icon suggestions:
Eyefor previewCode2for source- New icon for live preview mode
- Add
ViewModetype and updatepreviewModesref - Make Monaco editor transparent in live preview mode
- Make markdown preview layer pass clicks through to editor
- Add click-to-cursor-position mapping
- Update toolbar with new toggle
- Sync scroll positions between preview and source
- Handle cursor visibility
| File | Lines | Purpose |
|---|---|---|
src/renderer/components/shared/FileViewer.tsx |
237-242 | State management |
src/renderer/components/shared/FileViewer.tsx |
776-779 | Toggle handler |
src/renderer/components/shared/FileViewer.tsx |
1000-1028 | Preview/editor visibility |
src/renderer/components/shared/file-viewer/FileViewerToolbar.tsx |
39-51 | Toggle button UI |
The trickiest part is click-to-cursor-position mapping. The current findSelectionLineRange() maps selected text back to source lines. For live preview, we need to map click coordinates to cursor position.
Options:
- Use Monaco's coordinate conversion APIs
- Pre-calculate line positions in rendered markdown
- Simplified heuristic based on character offset