remove faulty undo/redo and replaced with back/forward buttons

This commit is contained in:
tusharmagar 2026-01-27 08:39:10 +05:30
parent 4d2fc01f88
commit d05344861a
3 changed files with 97 additions and 17 deletions

View file

@ -382,6 +382,8 @@ function ChatInputWithMentions({
function App() { function App() {
// File browser state (for Knowledge section) // File browser state (for Knowledge section)
const [selectedPath, setSelectedPath] = useState<string | null>(null) const [selectedPath, setSelectedPath] = useState<string | null>(null)
const [fileHistoryBack, setFileHistoryBack] = useState<string[]>([])
const [fileHistoryForward, setFileHistoryForward] = useState<string[]>([])
const [fileContent, setFileContent] = useState<string>('') const [fileContent, setFileContent] = useState<string>('')
const [editorContent, setEditorContent] = useState<string>('') const [editorContent, setEditorContent] = useState<string>('')
const [tree, setTree] = useState<TreeNode[]>([]) const [tree, setTree] = useState<TreeNode[]>([])
@ -1075,6 +1077,52 @@ function App() {
setIsGraphOpen(false) setIsGraphOpen(false)
}, []) }, [])
// File navigation with history tracking
const navigateToFile = useCallback((path: string | null) => {
if (path === selectedPath) return
// Push current path to back history (if we have one)
if (selectedPath) {
setFileHistoryBack(prev => [...prev, selectedPath])
}
// Clear forward history when navigating to a new file
setFileHistoryForward([])
setSelectedPath(path)
}, [selectedPath])
const navigateBack = useCallback(() => {
if (fileHistoryBack.length === 0) return
const newBack = [...fileHistoryBack]
const previousPath = newBack.pop()!
// Push current path to forward history
if (selectedPath) {
setFileHistoryForward(prev => [...prev, selectedPath])
}
setFileHistoryBack(newBack)
setSelectedPath(previousPath)
}, [fileHistoryBack, selectedPath])
const navigateForward = useCallback(() => {
if (fileHistoryForward.length === 0) return
const newForward = [...fileHistoryForward]
const nextPath = newForward.pop()!
// Push current path to back history
if (selectedPath) {
setFileHistoryBack(prev => [...prev, selectedPath])
}
setFileHistoryForward(newForward)
setSelectedPath(nextPath)
}, [fileHistoryForward, selectedPath])
const canNavigateBack = fileHistoryBack.length > 0
const canNavigateForward = fileHistoryForward.length > 0
// Handle image upload for the markdown editor // Handle image upload for the markdown editor
const handleImageUpload = useCallback(async (file: File): Promise<string | null> => { const handleImageUpload = useCallback(async (file: File): Promise<string | null> => {
try { try {
@ -1128,7 +1176,7 @@ function App() {
const toggleExpand = (path: string, kind: 'file' | 'dir') => { const toggleExpand = (path: string, kind: 'file' | 'dir') => {
if (kind === 'file') { if (kind === 'file') {
setSelectedPath(path) navigateToFile(path)
setIsGraphOpen(false) setIsGraphOpen(false)
return return
} }
@ -1312,9 +1360,9 @@ function App() {
const openWikiLink = useCallback(async (wikiPath: string) => { const openWikiLink = useCallback(async (wikiPath: string) => {
const resolvedPath = await ensureWikiFile(wikiPath) const resolvedPath = await ensureWikiFile(wikiPath)
if (resolvedPath) { if (resolvedPath) {
setSelectedPath(resolvedPath) navigateToFile(resolvedPath)
} }
}, [ensureWikiFile, setSelectedPath]) }, [ensureWikiFile, navigateToFile])
const wikiLinkConfig = React.useMemo(() => ({ const wikiLinkConfig = React.useMemo(() => ({
files: knowledgeFiles, files: knowledgeFiles,
@ -1616,7 +1664,7 @@ function App() {
error={graphStatus === 'error' ? (graphError ?? 'Failed to build graph') : null} error={graphStatus === 'error' ? (graphError ?? 'Failed to build graph') : null}
onSelectNode={(path) => { onSelectNode={(path) => {
setIsGraphOpen(false) setIsGraphOpen(false)
setSelectedPath(path) navigateToFile(path)
}} }}
/> />
</div> </div>
@ -1629,6 +1677,10 @@ function App() {
placeholder="Start writing..." placeholder="Start writing..."
wikiLinks={wikiLinkConfig} wikiLinks={wikiLinkConfig}
onImageUpload={handleImageUpload} onImageUpload={handleImageUpload}
onNavigateBack={navigateBack}
onNavigateForward={navigateForward}
canNavigateBack={canNavigateBack}
canNavigateForward={canNavigateForward}
/> />
</div> </div>
) : ( ) : (

View file

@ -22,8 +22,8 @@ import {
MinusIcon, MinusIcon,
LinkIcon, LinkIcon,
CodeSquareIcon, CodeSquareIcon,
Undo2Icon, ChevronLeftIcon,
Redo2Icon, ChevronRightIcon,
ExternalLinkIcon, ExternalLinkIcon,
Trash2Icon, Trash2Icon,
ImageIcon, ImageIcon,
@ -33,9 +33,21 @@ interface EditorToolbarProps {
editor: Editor | null editor: Editor | null
onSelectionHighlight?: (range: { from: number; to: number } | null) => void onSelectionHighlight?: (range: { from: number; to: number } | null) => void
onImageUpload?: (file: File) => Promise<void> | void onImageUpload?: (file: File) => Promise<void> | void
onNavigateBack?: () => void
onNavigateForward?: () => void
canNavigateBack?: boolean
canNavigateForward?: boolean
} }
export function EditorToolbar({ editor, onSelectionHighlight, onImageUpload }: EditorToolbarProps) { export function EditorToolbar({
editor,
onSelectionHighlight,
onImageUpload,
onNavigateBack,
onNavigateForward,
canNavigateBack,
canNavigateForward,
}: EditorToolbarProps) {
const [linkUrl, setLinkUrl] = useState('') const [linkUrl, setLinkUrl] = useState('')
const [isLinkPopoverOpen, setIsLinkPopoverOpen] = useState(false) const [isLinkPopoverOpen, setIsLinkPopoverOpen] = useState(false)
const fileInputRef = useRef<HTMLInputElement>(null) const fileInputRef = useRef<HTMLInputElement>(null)
@ -105,24 +117,24 @@ export function EditorToolbar({ editor, onSelectionHighlight, onImageUpload }: E
return ( return (
<div className="editor-toolbar"> <div className="editor-toolbar">
{/* Undo / Redo */} {/* Back / Forward Navigation */}
<Button <Button
variant="ghost" variant="ghost"
size="icon-sm" size="icon-sm"
onClick={() => editor.chain().focus().undo().run()} onClick={onNavigateBack}
disabled={!editor.can().undo()} disabled={!canNavigateBack}
title="Undo (Ctrl+Z)" title="Go back"
> >
<Undo2Icon className="size-4" /> <ChevronLeftIcon className="size-4" />
</Button> </Button>
<Button <Button
variant="ghost" variant="ghost"
size="icon-sm" size="icon-sm"
onClick={() => editor.chain().focus().redo().run()} onClick={onNavigateForward}
disabled={!editor.can().redo()} disabled={!canNavigateForward}
title="Redo (Ctrl+Shift+Z)" title="Go forward"
> >
<Redo2Icon className="size-4" /> <ChevronRightIcon className="size-4" />
</Button> </Button>
<div className="separator" /> <div className="separator" />

View file

@ -30,6 +30,10 @@ interface MarkdownEditorProps {
placeholder?: string placeholder?: string
wikiLinks?: WikiLinkConfig wikiLinks?: WikiLinkConfig
onImageUpload?: (file: File) => Promise<string | null> onImageUpload?: (file: File) => Promise<string | null>
onNavigateBack?: () => void
onNavigateForward?: () => void
canNavigateBack?: boolean
canNavigateForward?: boolean
} }
type WikiLinkMatch = { type WikiLinkMatch = {
@ -78,6 +82,10 @@ export function MarkdownEditor({
placeholder = 'Start writing...', placeholder = 'Start writing...',
wikiLinks, wikiLinks,
onImageUpload, onImageUpload,
onNavigateBack,
onNavigateForward,
canNavigateBack,
canNavigateForward,
}: MarkdownEditorProps) { }: MarkdownEditorProps) {
const isInternalUpdate = useRef(false) const isInternalUpdate = useRef(false)
const wrapperRef = useRef<HTMLDivElement>(null) const wrapperRef = useRef<HTMLDivElement>(null)
@ -318,7 +326,15 @@ export function MarkdownEditor({
return ( return (
<div className="tiptap-editor" onKeyDown={handleKeyDown}> <div className="tiptap-editor" onKeyDown={handleKeyDown}>
<EditorToolbar editor={editor} onSelectionHighlight={setSelectionHighlight} onImageUpload={handleImageUploadWithPlaceholder} /> <EditorToolbar
editor={editor}
onSelectionHighlight={setSelectionHighlight}
onImageUpload={handleImageUploadWithPlaceholder}
onNavigateBack={onNavigateBack}
onNavigateForward={onNavigateForward}
canNavigateBack={canNavigateBack}
canNavigateForward={canNavigateForward}
/>
<div className="editor-content-wrapper" ref={wrapperRef} onScroll={handleScroll}> <div className="editor-content-wrapper" ref={wrapperRef} onScroll={handleScroll}>
<EditorContent editor={editor} /> <EditorContent editor={editor} />
{wikiLinks ? ( {wikiLinks ? (