From 7617aad43181e3f997380d8087d9a9ab21f64acd Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Wed, 13 Nov 2024 21:37:47 +0000 Subject: [PATCH 01/22] simplify --- package-lock.json | 4 +- src/components/Editor/DocumentStats.tsx | 36 ++++++++++++++++++ src/components/Editor/EditorManager.tsx | 49 ++----------------------- src/contexts/FileContext.tsx | 6 --- 4 files changed, 42 insertions(+), 53 deletions(-) create mode 100644 src/components/Editor/DocumentStats.tsx diff --git a/package-lock.json b/package-lock.json index c59185c2..6fa1c8bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "reor-project", - "version": "0.2.26", + "version": "0.2.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "reor-project", - "version": "0.2.26", + "version": "0.2.29", "license": "AGPL-3.0", "dependencies": { "@aarkue/tiptap-math-extension": "^1.2.2", diff --git a/src/components/Editor/DocumentStats.tsx b/src/components/Editor/DocumentStats.tsx new file mode 100644 index 00000000..54720b15 --- /dev/null +++ b/src/components/Editor/DocumentStats.tsx @@ -0,0 +1,36 @@ +import React, { useEffect, useState } from 'react' +import { Editor } from '@tiptap/react' + +interface DocumentStatsProps { + editor: Editor | null +} + +const DocumentStats: React.FC = ({ editor }) => { + const [show, setShow] = useState(false) + + useEffect(() => { + const initDocumentStats = async () => { + const showStats = await window.electronStore.getDocumentStats() + setShow(showStats) + } + + initDocumentStats() + + const handleDocStatsChange = (event: Electron.IpcRendererEvent, value: boolean) => { + setShow(value) + } + + window.ipcRenderer.on('show-doc-stats-changed', handleDocStatsChange) + }, []) + + if (!editor || !show) return null + + return ( +
+
Characters: {editor.storage.characterCount.characters()}
+
Words: {editor.storage.characterCount.words()}
+
+ ) +} + +export default DocumentStats diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index e47db2ef..52ae374b 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -1,10 +1,9 @@ import React, { useEffect, useState } from 'react' import { EditorContent } from '@tiptap/react' -import InEditorBacklinkSuggestionsDisplay from './BacklinkSuggestionsDisplay' import EditorContextMenu from './EditorContextMenu' import SearchBar from './Search/SearchBar' import { useFileContext } from '@/contexts/FileContext' -import { useContentContext } from '@/contexts/ContentContext' +import DocumentStats from './DocumentStats' const EditorManager: React.FC = () => { const [showSearchBar, setShowSearchBar] = useState(false) @@ -12,9 +11,7 @@ const EditorManager: React.FC = () => { const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 }) const [editorFlex, setEditorFlex] = useState(true) - const { editor, suggestionsState, vaultFilesFlattened } = useFileContext() - const [showDocumentStats, setShowDocumentStats] = useState(false) - const { openContent } = useContentContext() + const { editor } = useFileContext() const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault() @@ -29,15 +26,6 @@ const EditorManager: React.FC = () => { if (contextMenuVisible) setContextMenuVisible(false) } - const handleClick = (event: React.MouseEvent) => { - const { target } = event - if (target instanceof HTMLElement && target.getAttribute('data-backlink') === 'true') { - event.preventDefault() - const backlinkPath = target.textContent - if (backlinkPath) openContent(backlinkPath) - } - } - useEffect(() => { const initEditorContentCenter = async () => { const isCenter = await window.electronStore.getEditorFlexCenter() @@ -52,21 +40,6 @@ const EditorManager: React.FC = () => { window.ipcRenderer.on('editor-flex-center-changed', handleEditorChange) }, []) - useEffect(() => { - const initDocumentStats = async () => { - const showStats = await window.electronStore.getDocumentStats() - setShowDocumentStats(showStats) - } - - initDocumentStats() - - const handleDocStatsChange = (event: Electron.IpcRendererEvent, value: boolean) => { - setShowDocumentStats(value) - } - - window.ipcRenderer.on('show-doc-stats-changed', handleDocStatsChange) - }, []) - return (
{ /> )} -
+
{ wordBreak: 'break-word', }} onContextMenu={handleContextMenu} - onClick={handleClick} editor={editor} />
- {suggestionsState && ( - file.relativePath)} - /> - )} - {editor && showDocumentStats && ( -
-
Characters: {editor.storage.characterCount.characters()}
-
Words: {editor.storage.characterCount.words()}
-
- )} +
) } diff --git a/src/contexts/FileContext.tsx b/src/contexts/FileContext.tsx index 3480dc77..87a02965 100644 --- a/src/contexts/FileContext.tsx +++ b/src/contexts/FileContext.tsx @@ -28,7 +28,6 @@ import { getNextAvailableFileNameGivenBaseName, sortFilesAndDirectories, } from '@/lib/file' -import { SuggestionsState } from '@/components/Editor/BacklinkSuggestionsDisplay' import HighlightExtension, { HighlightData } from '@/components/Editor/HighlightExtension' import { RichTextLink } from '@/components/Editor/RichTextLink' import '@/styles/tiptap.scss' @@ -49,7 +48,6 @@ type FileContextType = { navigationHistory: string[] addToNavigationHistory: (value: string) => void openOrCreateFile: (filePath: string, optionalContentToWriteOnCreate?: string) => Promise - suggestionsState: SuggestionsState | null | undefined spellCheckEnabled: boolean highlightData: HighlightData noteToBeRenamed: string @@ -57,7 +55,6 @@ type FileContextType = { fileDirToBeRenamed: string setFileDirToBeRenamed: React.Dispatch> renameFile: (oldFilePath: string, newFilePath: string) => Promise - setSuggestionsState: React.Dispatch> setSpellCheckEnabled: React.Dispatch> deleteFile: (path: string | undefined) => Promise selectedDirectory: string | null @@ -80,7 +77,6 @@ export const FileProvider: React.FC<{ children: ReactNode }> = ({ children }) => const [expandedDirectories, setExpandedDirectories] = useState>(new Map()) const [selectedDirectory, setSelectedDirectory] = useState(null) const [currentlyOpenFilePath, setCurrentlyOpenFilePath] = useState(null) - const [suggestionsState, setSuggestionsState] = useState() const [needToWriteEditorContentToDisk, setNeedToWriteEditorContentToDisk] = useState(false) const [needToIndexEditorContent, setNeedToIndexEditorContent] = useState(false) const [spellCheckEnabled, setSpellCheckEnabled] = useState(false) @@ -369,7 +365,6 @@ export const FileProvider: React.FC<{ children: ReactNode }> = ({ children }) => navigationHistory, addToNavigationHistory, openOrCreateFile, - suggestionsState, spellCheckEnabled, highlightData, noteToBeRenamed, @@ -377,7 +372,6 @@ export const FileProvider: React.FC<{ children: ReactNode }> = ({ children }) => fileDirToBeRenamed, setFileDirToBeRenamed, renameFile, - setSuggestionsState, setSpellCheckEnabled, deleteFile, selectedDirectory, From c9863e828f60f79d77d361b102f21fba5efd20ce Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Wed, 13 Nov 2024 21:59:38 +0000 Subject: [PATCH 02/22] setup bubble menu --- src/components/Editor/EditorManager.tsx | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index 52ae374b..58ef4345 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -1,5 +1,6 @@ +/* eslint-disable react/button-has-type */ import React, { useEffect, useState } from 'react' -import { EditorContent } from '@tiptap/react' +import { EditorContent, BubbleMenu } from '@tiptap/react' import EditorContextMenu from './EditorContextMenu' import SearchBar from './Search/SearchBar' import { useFileContext } from '@/contexts/FileContext' @@ -45,6 +46,32 @@ const EditorManager: React.FC = () => { className="relative size-full cursor-text overflow-hidden bg-dark-gray-c-eleven py-4 text-slate-400 opacity-80" onClick={() => editor?.commands.focus()} > + {editor && ( + + + + + + )} {contextMenuVisible && ( Date: Wed, 13 Nov 2024 22:05:16 +0000 Subject: [PATCH 03/22] test hide --- src/components/Editor/EditorManager.tsx | 27 ++++++++----------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index 58ef4345..7e1c9ef4 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -11,7 +11,7 @@ const EditorManager: React.FC = () => { const [contextMenuVisible, setContextMenuVisible] = useState(false) const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 }) const [editorFlex, setEditorFlex] = useState(true) - + const [showAIPopup, setShowAIPopup] = useState(false) const { editor } = useFileContext() const handleContextMenu = (event: React.MouseEvent) => { @@ -52,24 +52,13 @@ const EditorManager: React.FC = () => { editor={editor} tippyOptions={{ duration: 100 }} > - - - + {showAIPopup ? ( +
test hide
+ ) : ( + + )} )} From cd761f3ee3b98e5c6fa18038bae56df0eedeb620 Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Wed, 13 Nov 2024 22:31:54 +0000 Subject: [PATCH 04/22] on shown logic --- src/components/Editor/EditorManager.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index 7e1c9ef4..f57c171b 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -50,7 +50,12 @@ const EditorManager: React.FC = () => { { + setShowAIPopup(false) + }, + }} > {showAIPopup ? (
test hide
From 1258003bb05da7ccc7d447ba1da53031b52e1d04 Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Wed, 13 Nov 2024 22:34:20 +0000 Subject: [PATCH 05/22] on hide --- src/components/Editor/EditorManager.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index f57c171b..dc6f0a17 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -52,7 +52,7 @@ const EditorManager: React.FC = () => { editor={editor} tippyOptions={{ duration: 100, - onShown: () => { + onHidden: () => { setShowAIPopup(false) }, }} From fa837e71e01575ebfabd268577ef393323612eab Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Wed, 13 Nov 2024 22:40:02 +0000 Subject: [PATCH 06/22] initial ai edit button --- src/components/Editor/AIEdit.tsx | 85 +++++++++++++++++++++++++ src/components/Editor/EditorManager.tsx | 3 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/components/Editor/AIEdit.tsx diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx new file mode 100644 index 00000000..b55d2eb7 --- /dev/null +++ b/src/components/Editor/AIEdit.tsx @@ -0,0 +1,85 @@ +import React from 'react' +import { useCompletion } from 'ai/react' +import { ArrowUp, Sparkles, ShrinkIcon, ExpandIcon, Play } from 'lucide-react' +import { Button } from '@/components/ui/button' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' + +interface AiEditMenuProps { + selectedText: string + onEdit: (newText: string) => void +} + +const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => { + const { complete } = useCompletion({ + api: '/api/generate', + }) + + const handleAction = async (action: string) => { + const prompt = `${action} the following text: ${selectedText}` + const completion = await complete(prompt) + if (completion) { + onEdit(completion) + } + } + + return ( + + +
+ + Ask AI to edit or generate... +
+ +
+ +
+

Edit or review selection

+
+ + + + +
+
+
+

Use AI to do more

+ +
+
+
+ ) +} + +export default AiEditMenu diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index dc6f0a17..e296761f 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -5,6 +5,7 @@ import EditorContextMenu from './EditorContextMenu' import SearchBar from './Search/SearchBar' import { useFileContext } from '@/contexts/FileContext' import DocumentStats from './DocumentStats' +import AiEditMenu from './AIEdit' const EditorManager: React.FC = () => { const [showSearchBar, setShowSearchBar] = useState(false) @@ -58,7 +59,7 @@ const EditorManager: React.FC = () => { }} > {showAIPopup ? ( -
test hide
+ {}} /> ) : ( - )} +
{ + e.preventDefault() + e.stopPropagation() + }} + > + {showAIPopup ? ( + {}} /> + ) : ( + + )} +
)} From 5a861f82f98296f8b1d8be5ddea5c88f008eb0fd Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Thu, 14 Nov 2024 21:10:26 +0000 Subject: [PATCH 09/22] working input field --- src/components/Editor/EditorManager.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index dbb9b385..e7a5cf25 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -5,7 +5,6 @@ import EditorContextMenu from './EditorContextMenu' import SearchBar from './Search/SearchBar' import { useFileContext } from '@/contexts/FileContext' import DocumentStats from './DocumentStats' -import AiEditMenu from './AIEdit' const EditorManager: React.FC = () => { const [showSearchBar, setShowSearchBar] = useState(false) @@ -52,9 +51,10 @@ const EditorManager: React.FC = () => { className="flex gap-2 rounded-lg border border-gray-700 bg-dark-gray-c-eleven p-2 shadow-lg" editor={editor} tippyOptions={{ - duration: 1000, placement: 'auto', offset: [0, 10], + interactive: true, + interactiveBorder: 20, onHidden: () => { setShowAIPopup(false) }, @@ -65,9 +65,19 @@ const EditorManager: React.FC = () => { e.preventDefault() e.stopPropagation() }} + onClick={(e) => { + e.preventDefault() + e.stopPropagation() + }} > {showAIPopup ? ( - {}} /> + e.stopPropagation()} + onMouseDown={(e) => e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + className="bg-dark-gray-c-twelve rounded border border-gray-700 px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500" + /> ) : ( - - -
-

Edit or review selection

-
- - - - -
-
-
-

Use AI to do more

- -
-
- +
+ e.stopPropagation()} + onMouseDown={(e) => e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + className="z-50 flex w-full flex-col overflow-hidden rounded border-2 border-solid border-border bg-background text-white focus-within:ring-1 focus-within:ring-ring" + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus + /> +
) } diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index 312b0673..de95eb92 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -82,7 +82,7 @@ const EditorManager: React.FC = () => { {}} /> ) : ( )}
diff --git a/src/components/MainPage.tsx b/src/components/MainPage.tsx index c1243818..44feb7be 100644 --- a/src/components/MainPage.tsx +++ b/src/components/MainPage.tsx @@ -13,7 +13,6 @@ import IconsSidebar from './Sidebars/IconsSidebar' import SidebarManager from './Sidebars/MainSidebar' import EmptyPage from './Common/EmptyPage' import { ContentProvider, useContentContext } from '../contexts/ContentContext' -import WritingAssistant from './WritingAssistant/WritingAssistant' import { ChatProvider, useChatContext } from '@/contexts/ChatContext' import { FileProvider, useFileContext } from '@/contexts/FileContext' import ModalProvider from '@/contexts/ModalContext' @@ -40,7 +39,6 @@ const MainContent: React.FC = () => { )} - ) } From 03ce49a026747ed8bb38ad21a0b1128befd87e6b Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Thu, 14 Nov 2024 21:51:05 +0000 Subject: [PATCH 12/22] llm streaming --- src/components/Editor/AIEdit.tsx | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx index befcc11c..2ce36d0d 100644 --- a/src/components/Editor/AIEdit.tsx +++ b/src/components/Editor/AIEdit.tsx @@ -1,5 +1,9 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import React from 'react' +import { ArrowUp } from 'lucide-react' +import React, { useState } from 'react' +import { streamText } from 'ai' +import { Button } from '../ui/button' +import resolveLLMClient from '@/lib/llm/client' interface AiEditMenuProps { selectedText: string @@ -7,6 +11,21 @@ interface AiEditMenuProps { } const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => { + const [response, setResponse] = useState('') + + const handleEdit = async () => { + const defaultLLMName = await window.llm.getDefaultLLMName() + const llmClient = await resolveLLMClient(defaultLLMName) + const { textStream } = await streamText({ + model: llmClient, + messages: [{ role: 'user', content: `Edit the following text: ${selectedText}` }], + }) + + // eslint-disable-next-line no-restricted-syntax + for await (const textPart of textStream) { + setResponse((prev) => prev + textPart) + } + } return (
{ // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus /> +
) } From a84c70eaecaffa726298f7bdac17e08b884f4110 Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Thu, 14 Nov 2024 21:58:16 +0000 Subject: [PATCH 13/22] show response --- src/components/Editor/AIEdit.tsx | 71 ++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx index 2ce36d0d..3042f113 100644 --- a/src/components/Editor/AIEdit.tsx +++ b/src/components/Editor/AIEdit.tsx @@ -12,34 +12,61 @@ interface AiEditMenuProps { const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => { const [response, setResponse] = useState('') + const [isLoading, setIsLoading] = useState(false) const handleEdit = async () => { - const defaultLLMName = await window.llm.getDefaultLLMName() - const llmClient = await resolveLLMClient(defaultLLMName) - const { textStream } = await streamText({ - model: llmClient, - messages: [{ role: 'user', content: `Edit the following text: ${selectedText}` }], - }) + try { + setIsLoading(true) + setResponse('') + const defaultLLMName = await window.llm.getDefaultLLMName() + const llmClient = await resolveLLMClient(defaultLLMName) + const { textStream } = await streamText({ + model: llmClient, + messages: [{ role: 'user', content: `Edit the following text: ${selectedText}` }], + }) - // eslint-disable-next-line no-restricted-syntax - for await (const textPart of textStream) { - setResponse((prev) => prev + textPart) + // eslint-disable-next-line no-restricted-syntax + for await (const textPart of textStream) { + setResponse((prev) => prev + textPart) + } + } finally { + setIsLoading(false) } } + return ( -
- e.stopPropagation()} - onMouseDown={(e) => e.stopPropagation()} - onKeyDown={(e) => e.stopPropagation()} - className="z-50 flex w-full flex-col overflow-hidden rounded border-2 border-solid border-border bg-background text-white focus-within:ring-1 focus-within:ring-ring" - // eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus - /> - +
+ {(response || isLoading) && ( +
+ {isLoading && !response &&
Generating response...
} + {response && ( +
+

{response}

+
+ )} +
+ )} + +
+ e.stopPropagation()} + onMouseDown={(e) => e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + className="z-50 flex w-full flex-col overflow-hidden rounded border-2 border-solid border-border bg-background text-white focus-within:ring-1 focus-within:ring-ring" + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus + /> + +
) } From 94320ca93c8a13c02bc367f4de19e8a7bf18d5bd Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Thu, 14 Nov 2024 22:09:13 +0000 Subject: [PATCH 14/22] constraints working --- src/components/Editor/AIEdit.tsx | 4 ++-- src/components/Editor/EditorManager.tsx | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx index 3042f113..2d578ac6 100644 --- a/src/components/Editor/AIEdit.tsx +++ b/src/components/Editor/AIEdit.tsx @@ -40,8 +40,8 @@ const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => {
{isLoading && !response &&
Generating response...
} {response && ( -
-

{response}

+
+

{response}

)}
diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index de95eb92..d67a44b9 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -59,9 +59,11 @@ const EditorManager: React.FC = () => { onHidden: () => { setShowAIPopup(false) }, + maxWidth: 'none', }} >
{ e.preventDefault() e.stopPropagation() @@ -72,17 +74,12 @@ const EditorManager: React.FC = () => { }} > {showAIPopup ? ( - // e.stopPropagation()} - // onMouseDown={(e) => e.stopPropagation()} - // onKeyDown={(e) => e.stopPropagation()} - // className="bg-dark-gray-c-twelve rounded border border-gray-700 px-2 py-1 focus:outline-none focus:ring-1 focus:ring-blue-500" - // /> + //
{}} /> ) : ( + //
)}
From 62c6ecb0a1f9e45a2431afe846adda6bda4896ae Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Fri, 15 Nov 2024 17:15:07 +0000 Subject: [PATCH 15/22] improving writing assistant --- src/components/Editor/AIEdit.tsx | 41 ++++++++++++++++--- src/components/Editor/EditorManager.tsx | 15 ++++++- src/components/TitleBar/NavigationButtons.tsx | 2 +- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx index 2d578ac6..6e97396b 100644 --- a/src/components/Editor/AIEdit.tsx +++ b/src/components/Editor/AIEdit.tsx @@ -13,6 +13,7 @@ interface AiEditMenuProps { const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => { const [response, setResponse] = useState('') const [isLoading, setIsLoading] = useState(false) + const [instruction, setInstruction] = useState('') const handleEdit = async () => { try { @@ -22,7 +23,17 @@ const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => { const llmClient = await resolveLLMClient(defaultLLMName) const { textStream } = await streamText({ model: llmClient, - messages: [{ role: 'user', content: `Edit the following text: ${selectedText}` }], + messages: [ + { + role: 'system', + content: + "Edit the user provided text following the user's instruction. You must respond in the same language as the user's instruction and only return the edited text.", + }, + { + role: 'user', + content: `Instruction: ${instruction}\nText: ${selectedText}`, + }, + ], }) // eslint-disable-next-line no-restricted-syntax @@ -40,9 +51,21 @@ const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => {
{isLoading && !response &&
Generating response...
} {response && ( -
-

{response}

-
+ <> +
+

{response}

+
+
+ +
+ )}
)} @@ -50,9 +73,17 @@ const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => {
setInstruction(e.target.value)} + placeholder="Enter your editing instruction..." onClick={(e) => e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()} - onKeyDown={(e) => e.stopPropagation()} + onKeyDown={(e) => { + e.stopPropagation() + if (e.key === 'Enter' && !isLoading) { + handleEdit() + } + }} className="z-50 flex w-full flex-col overflow-hidden rounded border-2 border-solid border-border bg-background text-white focus-within:ring-1 focus-within:ring-ring" // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus diff --git a/src/components/Editor/EditorManager.tsx b/src/components/Editor/EditorManager.tsx index d67a44b9..1b590297 100644 --- a/src/components/Editor/EditorManager.tsx +++ b/src/components/Editor/EditorManager.tsx @@ -75,7 +75,20 @@ const EditorManager: React.FC = () => { > {showAIPopup ? ( //
- {}} /> + { + editor + .chain() + .focus() + .deleteRange({ + from: editor.state.selection.from, + to: editor.state.selection.to, + }) + .insertContent(newText) + .run() + }} + /> ) : ( //
From a761a22b641f23842f32602301cf73a97b9bb88b Mon Sep 17 00:00:00 2001 From: samlhuillier Date: Fri, 15 Nov 2024 21:04:58 +0000 Subject: [PATCH 18/22] background --- src/components/Editor/AIEdit.tsx | 2 +- src/components/Editor/EditorManager.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Editor/AIEdit.tsx b/src/components/Editor/AIEdit.tsx index 772df22a..70a9558b 100644 --- a/src/components/Editor/AIEdit.tsx +++ b/src/components/Editor/AIEdit.tsx @@ -70,7 +70,7 @@ const AiEditMenu = ({ selectedText, onEdit }: AiEditMenuProps) => {
)} -
+