diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..04ac4c0 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,14 @@ + + + + + Annotation Tooltip Demo + + + +
+ + + diff --git a/demo/main.tsx b/demo/main.tsx new file mode 100644 index 0000000..6346a21 --- /dev/null +++ b/demo/main.tsx @@ -0,0 +1,68 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import { useEditorStore } from '@renderer/store/editorStore' +import { MarkdownEditor } from '@renderer/components/Editor/MarkdownEditor' +import '@renderer/styles/global.css' + +// Mock window.api so the renderer doesn't crash in a plain browser context +;(window as unknown as Record).api = { + listFiles: () => Promise.resolve([]), + readFile: () => Promise.resolve(''), + writeFile: () => Promise.resolve(), + streamAIMessage: () => Promise.resolve(), + removeAIListener: () => {}, + getProjectWordCount: () => Promise.resolve(0), + saveOrder: () => Promise.resolve() +} + +const DEMO_TEXT = + `She was seen by him walking down the cobblestone path.\n\n` + + `The old manuscript was written by an unknown author many centuries ago.\n\n` + + `The message had been delivered by the courier at dawn.` + +// Compute annotation character ranges directly from the text +const a1s = DEMO_TEXT.indexOf('She was seen') +const a1e = DEMO_TEXT.indexOf('.', a1s) + 1 +const a2s = DEMO_TEXT.indexOf('The old manuscript') +const a2e = DEMO_TEXT.indexOf('.', a2s) + 1 +const a3s = DEMO_TEXT.indexOf('The message') +const a3e = DEMO_TEXT.indexOf('.', a3s) + 1 + +// Pre-seed store before React renders so all three effects fire correctly on mount +const store = useEditorStore.getState() +store.setActiveFile('demo.md', DEMO_TEXT) +store.setAnnotations([ + { + id: 'ann-1', + type: 'passive_voice', + from: a1s, + to: a1e, + matchedText: 'was seen by', + message: 'Passive voice weakens the narrative tension here — placing the subject in an active role would make the sentence more immediate and visceral, which is essential for gothic prose where atmosphere must feel alive and urgent\u2026', + suggestion: 'He saw her walking down the cobblestone path.' + }, + { + id: 'ann-2', + type: 'passive_voice', + from: a2s, + to: a2e, + matchedText: 'was written by', + message: 'Passive construction distances the reader from the action; consider foregrounding the actor to strengthen the historical atmosphere.', + suggestion: 'An unknown author wrote the old manuscript many centuries ago.' + }, + { + id: 'ann-3', + type: 'style', + from: a3s, + to: a3e, + matchedText: 'had been delivered by', + message: 'Wordy passive construction: "had been delivered by"', + suggestion: 'The courier delivered the message at dawn.' + } +]) + +createRoot(document.getElementById('root')!).render( + + + +) diff --git a/src/main/aiService.ts b/src/main/aiService.ts index 037a760..e4815e3 100644 --- a/src/main/aiService.ts +++ b/src/main/aiService.ts @@ -66,7 +66,27 @@ For each suggestion: ISSUE: [type: Pacing / Sentence Variety / Show-Don't-Tell / Atmosphere / Dialogue] PASSAGE: "[exact quoted text]" PROBLEM: [specific explanation] -SUGGESTION: [concrete rewrite or approach]` +SUGGESTION: [concrete rewrite or approach]`, + + critique: `Give an honest, detailed critique of this chapter as a whole. Structure your response as follows: + +**Overall impression** (2–3 sentences on what the chapter achieves and its most significant weakness) + +**What works well** +Identify 2–4 specific strengths — scenes, lines, or moments that land effectively. Quote the passage and explain why it works. + +STRENGTH: "[exact quoted passage]" +WHY: [explanation] + +**What needs work** +Identify 2–4 areas where the chapter falls short. Be direct. Quote the passage and give a concrete direction for improvement. + +ISSUE: "[exact quoted passage]" +PROBLEM: [explanation] +SUGGESTION: [concrete direction] + +**One priority** +Name the single most important thing to fix in a revision of this chapter.` } return `${chapterContext}\n\n${modeInstructions[payload.mode]}` diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index b6464ea..048848d 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { FileTree } from './components/FileTree/FileTree' import { MarkdownEditor } from './components/Editor/MarkdownEditor' import { ChatPanel } from './components/AIChat/ChatPanel' @@ -9,6 +9,8 @@ import './styles/app.css' export default function App(): JSX.Element { const { setFileTree, activeFilePath, isDirty, markSaved, activeFileContent, theme, toggleTheme } = useEditorStore() + const [sidebarOpen, setSidebarOpen] = useState(true) + const [chatOpen, setChatOpen] = useState(true) // Load file tree on mount and apply persisted theme useEffect(() => { @@ -32,16 +34,35 @@ export default function App(): JSX.Element { }, [activeFilePath, isDirty, activeFileContent]) return ( -
+
Hohoff Editor - +
+
+
+ +