mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
fix: address code review feedback from PR #423
Addresses feedback from gemini-code-assist and coderabbitai reviewers: ## Duplicate Code (High Priority) - Extract `getEffectiveDefaultEditor` logic into shared `useEffectiveDefaultEditor` hook - Both account-section.tsx and worktree-actions-dropdown.tsx now use the shared hook ## Performance (Medium Priority) - Refactor `detectAllEditors` to use `Promise.all` for parallel editor detection - Replace sequential `await tryAddEditor()` calls with parallel `findEditor()` checks ## Code Quality (Medium Priority) - Remove verbose IIFE pattern for editor icon rendering - Pre-compute icon components before JSX return statement ## Bug Fixes - Use `os.homedir()` instead of `~` fallback which doesn't expand in shell - Normalize Select value to 'auto' when saved editor command not found in editors - Add defensive check for empty editors array in useEffectiveDefaultEditor - Improve mock openInEditor to correctly map all editor commands to display names Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,9 +28,8 @@ import {
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { WorktreeInfo, DevServerInfo, PRInfo, GitRepoStatus } from '../types';
|
||||
import { TooltipWrapper } from './tooltip-wrapper';
|
||||
import { useAvailableEditors } from '../hooks/use-available-editors';
|
||||
import { useAvailableEditors, useEffectiveDefaultEditor } from '../hooks/use-available-editors';
|
||||
import { getEditorIcon } from '@/components/icons/editor-icons';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
interface WorktreeActionsDropdownProps {
|
||||
worktree: WorktreeInfo;
|
||||
@@ -84,30 +83,19 @@ export function WorktreeActionsDropdown({
|
||||
onOpenDevServerUrl,
|
||||
}: WorktreeActionsDropdownProps) {
|
||||
// Get available editors for the "Open In" submenu
|
||||
const { editors, hasMultipleEditors } = useAvailableEditors();
|
||||
const { editors } = useAvailableEditors();
|
||||
|
||||
// Get the user's preferred default editor from settings
|
||||
const defaultEditorCommand = useAppStore((s) => s.defaultEditorCommand);
|
||||
|
||||
// Calculate effective default editor based on user setting or auto-detect (Cursor > VS Code > first)
|
||||
const getEffectiveDefaultEditor = () => {
|
||||
if (defaultEditorCommand) {
|
||||
const found = editors.find((e) => e.command === defaultEditorCommand);
|
||||
if (found) return found;
|
||||
}
|
||||
// Auto-detect: prefer Cursor, then VS Code, then first available
|
||||
const cursor = editors.find((e) => e.command === 'cursor');
|
||||
if (cursor) return cursor;
|
||||
const vscode = editors.find((e) => e.command === 'code');
|
||||
if (vscode) return vscode;
|
||||
return editors[0];
|
||||
};
|
||||
|
||||
const effectiveDefaultEditor = getEffectiveDefaultEditor();
|
||||
// Use shared hook for effective default editor
|
||||
const effectiveDefaultEditor = useEffectiveDefaultEditor(editors);
|
||||
|
||||
// Get other editors (excluding the default) for the submenu
|
||||
const otherEditors = editors.filter((e) => e.command !== effectiveDefaultEditor?.command);
|
||||
|
||||
// Get icon component for the effective editor (avoid IIFE in JSX)
|
||||
const DefaultEditorIcon = effectiveDefaultEditor
|
||||
? getEditorIcon(effectiveDefaultEditor.command)
|
||||
: null;
|
||||
|
||||
// Check if there's a PR associated with this worktree from stored metadata
|
||||
const hasPR = !!worktree.pr;
|
||||
|
||||
@@ -240,10 +228,7 @@ export function WorktreeActionsDropdown({
|
||||
onClick={() => onOpenInEditor(worktree, effectiveDefaultEditor.command)}
|
||||
className="text-xs flex-1 pr-0 rounded-r-none"
|
||||
>
|
||||
{(() => {
|
||||
const EditorIcon = getEditorIcon(effectiveDefaultEditor.command);
|
||||
return <EditorIcon className="w-3.5 h-3.5 mr-2" />;
|
||||
})()}
|
||||
{DefaultEditorIcon && <DefaultEditorIcon className="w-3.5 h-3.5 mr-2" />}
|
||||
Open in {effectiveDefaultEditor.name}
|
||||
</DropdownMenuItem>
|
||||
{/* Chevron trigger for submenu with other editors and Copy Path */}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
|
||||
const logger = createLogger('AvailableEditors');
|
||||
|
||||
@@ -44,3 +45,30 @@ export function useAvailableEditors() {
|
||||
defaultEditor: editors[0] ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get the effective default editor based on user settings
|
||||
* Falls back to: Cursor > VS Code > first available editor
|
||||
*/
|
||||
export function useEffectiveDefaultEditor(editors: EditorInfo[]): EditorInfo | null {
|
||||
const defaultEditorCommand = useAppStore((s) => s.defaultEditorCommand);
|
||||
|
||||
return useMemo(() => {
|
||||
if (editors.length === 0) return null;
|
||||
|
||||
// If user has a saved preference and it exists in available editors, use it
|
||||
if (defaultEditorCommand) {
|
||||
const found = editors.find((e) => e.command === defaultEditorCommand);
|
||||
if (found) return found;
|
||||
}
|
||||
|
||||
// Auto-detect: prefer Cursor, then VS Code, then first available
|
||||
const cursor = editors.find((e) => e.command === 'cursor');
|
||||
if (cursor) return cursor;
|
||||
|
||||
const vscode = editors.find((e) => e.command === 'code');
|
||||
if (vscode) return vscode;
|
||||
|
||||
return editors[0];
|
||||
}, [editors, defaultEditorCommand]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user