Skip to content

Commit 69026f2

Browse files
authored
Merge branch 'main' into codex/enable-arrow-key-navigation-in-search-results
2 parents 43dc4c4 + 19b8133 commit 69026f2

3 files changed

Lines changed: 30 additions & 4 deletions

File tree

App.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import UpdateNotification from './components/UpdateNotification';
2222
import CreateFromTemplateModal from './components/CreateFromTemplateModal';
2323
import DocumentHistoryView from './components/PromptHistoryView';
2424
import FolderOverview, { type FolderOverviewMetrics, type FolderSearchResult, type RecentDocumentSummary, type DocTypeCount, type LanguageCount } from './components/FolderOverview';
25-
import { PlusIcon, FolderPlusIcon, TrashIcon, GearIcon, InfoIcon, TerminalIcon, DocumentDuplicateIcon, PencilIcon, CopyIcon, CommandIcon, CodeIcon, FolderDownIcon, FormatIcon, SparklesIcon, SaveIcon, CheckIcon, DatabaseIcon, ExpandAllIcon, CollapseAllIcon, ArrowUpIcon, ArrowDownIcon, LockClosedIcon, LockOpenIcon } from './components/Icons';
25+
import { PlusIcon, FolderPlusIcon, TrashIcon, GearIcon, InfoIcon, TerminalIcon, DocumentDuplicateIcon, PencilIcon, CopyIcon, CommandIcon, CodeIcon, FolderDownIcon, FormatIcon, SparklesIcon, SaveIcon, CheckIcon, DatabaseIcon, ExpandAllIcon, CollapseAllIcon, ArrowUpIcon, ArrowDownIcon, LockClosedIcon, LockOpenIcon, SearchIcon } from './components/Icons';
2626
import AboutModal from './components/AboutModal';
2727
import Header from './components/Header';
2828
import CustomTitleBar from './components/CustomTitleBar';
@@ -367,6 +367,7 @@ export const MainApp: React.FC = () => {
367367
const isLoggerResizing = useRef(false);
368368
const commandPaletteTargetRef = useRef<HTMLDivElement>(null);
369369
const commandPaletteInputRef = useRef<HTMLInputElement>(null);
370+
const documentTreeSearchInputRef = useRef<HTMLInputElement>(null);
370371
const dragCounter = useRef(0);
371372
const ensureNodeVisibleRef = useRef<(node: Pick<DocumentOrFolder, 'id' | 'type' | 'parentId'>) => void>();
372373

@@ -768,6 +769,14 @@ export const MainApp: React.FC = () => {
768769
setSelectedIds(new Set(navigableItems.map(item => item.id)));
769770
}, [navigableItems, setSelectedIds]);
770771

772+
const handleFocusDocumentTreeSearch = useCallback(() => {
773+
const input = documentTreeSearchInputRef.current;
774+
if (input) {
775+
input.focus();
776+
input.select();
777+
}
778+
}, [documentTreeSearchInputRef]);
779+
771780
const handleMoveSelectionUp = useCallback(() => {
772781
const primaryId = getPrimarySelectionId();
773782
if (!primaryId) {
@@ -2630,6 +2639,7 @@ export const MainApp: React.FC = () => {
26302639
{ id: 'rename-item', name: 'Rename Selected Item', action: handleRenameSelection, category: 'File', icon: PencilIcon, shortcut: ['F2'], keywords: 'rename edit title' },
26312640
{ id: 'delete-item', name: 'Delete Selection', action: () => handleDeleteSelection(selectedIds), category: 'File', icon: TrashIcon, shortcut: ['Delete'], keywords: 'remove discard' },
26322641
{ id: 'document-tree-select-all', name: 'Select All Tree Items', action: handleDocumentTreeSelectAll, category: 'Document Tree', icon: CheckIcon, shortcut: ['Control', 'A'], keywords: 'select highlight all tree' },
2642+
{ id: 'document-tree-focus-search', name: 'Focus Document Tree Search', action: handleFocusDocumentTreeSearch, category: 'Document Tree', icon: SearchIcon, shortcut: ['F4'], keywords: 'focus search tree find' },
26332643
{ id: 'document-tree-expand-all', name: 'Expand All Tree Folders', action: handleExpandAll, category: 'Document Tree', icon: ExpandAllIcon, shortcut: ['Control', 'Alt', 'ArrowRight'], keywords: 'open folders tree expand' },
26342644
{ id: 'document-tree-collapse-all', name: 'Collapse All Tree Folders', action: handleCollapseAll, category: 'Document Tree', icon: CollapseAllIcon, shortcut: ['Control', 'Alt', 'ArrowLeft'], keywords: 'close folders tree collapse' },
26352645
{ id: 'document-tree-move-selection-up', name: 'Move Selection Up', action: handleMoveSelectionUp, category: 'Document Tree', icon: ArrowUpIcon, shortcut: ['Alt', 'ArrowUp'], keywords: 'reorder move up tree' },
@@ -2644,7 +2654,7 @@ export const MainApp: React.FC = () => {
26442654
{ id: 'toggle-info', name: 'Toggle Info View', action: () => { addLog('INFO', 'Command: Toggle Info View.'); setView(v => v === 'info' ? 'editor' : 'info'); }, category: 'View', icon: InfoIcon, keywords: 'help docs readme' },
26452655
{ id: 'open-about', name: 'About DocForge', action: handleOpenAbout, category: 'Help', icon: SparklesIcon, keywords: 'about credits information' },
26462656
{ id: 'toggle-logs', name: 'Toggle Logs Panel', action: () => { addLog('INFO', 'Command: Toggle Logs Panel.'); setIsLoggerVisible(v => !v); }, category: 'View', icon: TerminalIcon, keywords: 'debug console' },
2647-
], [handleNewDocument, handleOpenNewCodeFileModal, handleNewRootFolder, handleNewSubfolder, handleDeleteSelection, handleNewTemplate, toggleSettingsView, handleDuplicateSelection, handleRenameSelection, selectedIds, addLog, handleToggleCommandPalette, handleFormatDocument, handleOpenAbout, handleNewDocumentFromClipboard, handleDocumentTreeSelectAll, handleExpandAll, handleCollapseAll, handleMoveSelectionUp, handleMoveSelectionDown, handleCopySelectionContent, handleSaveSelectionToFile, activeDocument?.locked, handleToggleActiveDocumentLock]);
2657+
], [handleNewDocument, handleOpenNewCodeFileModal, handleNewRootFolder, handleNewSubfolder, handleDeleteSelection, handleNewTemplate, toggleSettingsView, handleDuplicateSelection, handleRenameSelection, selectedIds, addLog, handleToggleCommandPalette, handleFormatDocument, handleOpenAbout, handleNewDocumentFromClipboard, handleDocumentTreeSelectAll, handleFocusDocumentTreeSearch, handleExpandAll, handleCollapseAll, handleMoveSelectionUp, handleMoveSelectionDown, handleCopySelectionContent, handleSaveSelectionToFile, activeDocument?.locked, handleToggleActiveDocumentLock]);
26482658

26492659
const enrichedCommands = useMemo(() => {
26502660
return commands.map(command => {
@@ -2800,7 +2810,7 @@ export const MainApp: React.FC = () => {
28002810
return;
28012811
}
28022812

2803-
if (command?.category === 'Document Tree') {
2813+
if (command?.category === 'Document Tree' && command.id !== 'document-tree-focus-search') {
28042814
const target = e.target as HTMLElement | null;
28052815
const isWithinSidebar = target?.closest('[data-component="document-tree-sidebar"]');
28062816
if (!isWithinSidebar) {
@@ -3022,6 +3032,7 @@ export const MainApp: React.FC = () => {
30223032
onCollapseAll={handleCollapseAll}
30233033
searchTerm={searchTerm}
30243034
setSearchTerm={setSearchTerm}
3035+
searchInputRef={documentTreeSearchInputRef}
30253036
onContextMenu={handleContextMenu}
30263037
renamingNodeId={renamingNodeId}
30273038
onRenameComplete={() => setRenamingNodeId(null)}

components/ContextMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({ isOpen, position, items, onCl
155155
maxHeight: menuStyle.maxHeight ? menuStyle.maxHeight : undefined,
156156
overflowY: menuStyle.overflowY,
157157
}}
158-
className="fixed z-50 w-56 rounded-md bg-secondary p-1.5 shadow-2xl border border-border-color animate-fade-in-fast"
158+
className="fixed z-50 w-[16.8rem] rounded-md bg-secondary p-1.5 shadow-2xl border border-border-color animate-fade-in-fast"
159159
>
160160
<ul className="space-y-1">
161161
{/* Fix: Restructured the type guard to check for a property on the desired object type directly, which ensures proper type narrowing for the MenuItem union. */}

components/Sidebar.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ interface SidebarProps {
5454
customShortcuts: Record<string, string[]>;
5555
pendingRevealId: string | null;
5656
onRevealHandled: () => void;
57+
searchInputRef: React.RefObject<HTMLInputElement>;
5758

5859
activeDocumentLocked: boolean;
5960

@@ -87,6 +88,7 @@ const findNodeAndSiblings = (nodes: DocumentNode[], id: string): {node: Document
8788

8889
const Sidebar: React.FC<SidebarProps> = (props) => {
8990
const { documentTree, navigableItems, searchTerm, setSearchTerm, setSelectedIds, lastClickedId, setLastClickedId, onContextMenu, renamingNodeId, onRenameComplete, onExpandAll, onCollapseAll, commands, pendingRevealId, onRevealHandled, onNewFromClipboard, customShortcuts, onSelectTemplate, onSelectNode } = props;
91+
const { documentTree, navigableItems, searchTerm, setSearchTerm, setSelectedIds, lastClickedId, setLastClickedId, onContextMenu, renamingNodeId, onRenameComplete, onExpandAll, onCollapseAll, commands, pendingRevealId, onRevealHandled, onNewFromClipboard, customShortcuts, searchInputRef } = props;
9092
const [focusedItemId, setFocusedItemId] = useState<string | null>(null);
9193
const [isTemplatesCollapsed, setIsTemplatesCollapsed] = useState(false);
9294
const [templatesPanelHeight, setTemplatesPanelHeight] = useState(DEFAULT_TEMPLATES_PANEL_HEIGHT);
@@ -354,6 +356,18 @@ const Sidebar: React.FC<SidebarProps> = (props) => {
354356
return;
355357
}
356358

359+
const focusSearchShortcut = getEffectiveShortcut('document-tree-focus-search');
360+
if (matchesShortcut(e, focusSearchShortcut)) {
361+
e.preventDefault();
362+
e.stopPropagation();
363+
const input = searchInputRef.current;
364+
if (input) {
365+
input.focus();
366+
input.select();
367+
}
368+
return;
369+
}
370+
357371
const copyShortcut = getEffectiveShortcut('document-tree-copy-content');
358372
if (matchesShortcut(e, copyShortcut)) {
359373
e.preventDefault();
@@ -460,6 +474,7 @@ const Sidebar: React.FC<SidebarProps> = (props) => {
460474
<div className="relative w-full">
461475
<SearchIcon className="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary pointer-events-none" />
462476
<input
477+
ref={searchInputRef}
463478
type="text"
464479
placeholder="Search..."
465480
value={searchTerm}

0 commit comments

Comments
 (0)