add show in finder

This commit is contained in:
Arjun 2026-05-15 12:11:50 +05:30
parent 41f783d504
commit f9ddc6549a
5 changed files with 46 additions and 1 deletions

View file

@ -679,6 +679,11 @@ export function setupIpcHandlers() {
const error = await shell.openPath(filePath);
return { error: error || undefined };
},
'shell:showItemInFolder': async (_event, args) => {
const filePath = resolveShellPath(args.path);
shell.showItemInFolder(filePath);
return { success: true };
},
'shell:readFileBase64': async (_event, args) => {
const filePath = resolveShellPath(args.path);
const stat = await fs.stat(filePath);

View file

@ -3966,6 +3966,12 @@ function App() {
document.body.removeChild(textarea)
})
},
revealInFileManager: (path: string, isDir: boolean) => {
const channel = isDir ? 'shell:openPath' : 'shell:showItemInFolder'
void window.ipc.invoke(channel, { path }).catch((err) => {
console.error('Failed to open in file manager:', err)
})
},
onOpenInNewTab: (path: string) => {
openFileInNewTab(path)
},
@ -4769,6 +4775,7 @@ function App() {
rename: knowledgeActions.rename,
remove: knowledgeActions.remove,
copyPath: knowledgeActions.copyPath,
revealInFileManager: knowledgeActions.revealInFileManager,
}}
/>
</div>

View file

@ -1,6 +1,6 @@
import * as React from 'react'
import { useEffect, useState, useMemo, useCallback, useRef } from 'react'
import { ArrowDown, ArrowUp, ChevronLeft, ChevronRight, X, Check, ListFilter, Filter, Search, Save, Copy, Pencil, Trash2 } from 'lucide-react'
import { ArrowDown, ArrowUp, ChevronLeft, ChevronRight, X, Check, ListFilter, Filter, Search, Save, Copy, FolderOpen, Pencil, Trash2 } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover'
import { Command, CommandInput, CommandList, CommandItem, CommandEmpty, CommandGroup } from '@/components/ui/command'
@ -103,9 +103,18 @@ type BasesViewProps = {
rename: (oldPath: string, newName: string, isDir: boolean) => Promise<void>
remove: (path: string) => Promise<void>
copyPath: (path: string) => void
revealInFileManager: (path: string, isDir: boolean) => void
}
}
function getFileManagerName(): string {
if (typeof navigator === 'undefined') return 'File Manager'
const platform = navigator.platform.toLowerCase()
if (platform.includes('mac')) return 'Finder'
if (platform.includes('win')) return 'Explorer'
return 'File Manager'
}
function collectFiles(nodes: TreeNode[]): { path: string; name: string; mtimeMs: number }[] {
return nodes.flatMap((n) =>
n.kind === 'file' && n.name.endsWith('.md')
@ -919,6 +928,10 @@ function NoteRow({
<Copy className="mr-2 size-4" />
Copy Path
</ContextMenuItem>
<ContextMenuItem onClick={() => actions?.revealInFileManager(note.path, false)}>
<FolderOpen className="mr-2 size-4" />
Open in {getFileManagerName()}
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem onClick={() => { setNewName(baseName); isSubmittingRef.current = false; setIsRenaming(true) }}>
<Pencil className="mr-2 size-4" />

View file

@ -11,6 +11,7 @@ import {
ExternalLink,
FilePlus,
Folder,
FolderOpen,
FolderPlus,
Globe,
AlertTriangle,
@ -119,9 +120,18 @@ type KnowledgeActions = {
rename: (path: string, newName: string, isDir: boolean) => Promise<void>
remove: (path: string) => Promise<void>
copyPath: (path: string) => void
revealInFileManager: (path: string, isDir: boolean) => void
onOpenInNewTab?: (path: string) => void
}
function getFileManagerName(): string {
if (typeof navigator === 'undefined') return 'File Manager'
const platform = navigator.platform.toLowerCase()
if (platform.includes('mac')) return 'Finder'
if (platform.includes('win')) return 'Explorer'
return 'File Manager'
}
type RunListItem = {
id: string
title?: string
@ -1177,11 +1187,13 @@ function KnowledgeSection({
},
}), [actions, deriveParent])
const fileManagerName = getFileManagerName()
const quickActions = [
{ icon: FilePlus, label: "New Note", action: () => wrappedActions.createNote() },
{ icon: FolderPlus, label: "New Folder", action: () => void wrappedActions.createFolder() },
{ icon: Network, label: "Graph View", action: () => actions.openGraph() },
{ icon: Table2, label: "Bases", action: () => actions.openBases() },
{ icon: FolderOpen, label: `Open in ${fileManagerName}`, action: () => actions.revealInFileManager('knowledge', true) },
]
return (
@ -1389,6 +1401,10 @@ function Tree({
<Copy className="mr-2 size-4" />
Copy Path
</ContextMenuItem>
<ContextMenuItem onClick={() => actions.revealInFileManager(item.path, isDir)}>
<FolderOpen className="mr-2 size-4" />
Open in {getFileManagerName()}
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem onClick={() => { setNewName(baseName); isSubmittingRef.current = false; setIsRenaming(true) }}>
<Pencil className="mr-2 size-4" />

View file

@ -489,6 +489,10 @@ const ipcSchemas = {
req: z.object({ path: z.string() }),
res: z.object({ error: z.string().optional() }),
},
'shell:showItemInFolder': {
req: z.object({ path: z.string() }),
res: z.object({ success: z.literal(true) }),
},
'shell:readFileBase64': {
req: z.object({ path: z.string() }),
res: z.object({ data: z.string(), mimeType: z.string(), size: z.number() }),