mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-20 23:13:07 +00:00
feat: add default IDE setting and multi-editor support with icons
Add comprehensive editor detection and selection system that allows users to configure their preferred IDE for opening branches and worktrees. ## Server-side Changes - Add `/api/worktree/available-editors` endpoint to detect installed editors - Support detection via CLI commands (cursor, code, zed, subl, etc.) - Support detection via macOS app bundles in /Applications and ~/Applications - Detect editors: Cursor, VS Code, Zed, Sublime Text, Windsurf, Trae, Rider, WebStorm, Xcode, Android Studio, Antigravity, and file managers ## UI Changes ### Editor Icons - Add new `editor-icons.tsx` with SVG icons for all supported editors - Icons: Cursor, VS Code, Zed, Sublime Text, Windsurf, Trae, Rider, WebStorm, Xcode, Android Studio, Antigravity, Finder - `getEditorIcon()` helper maps editor commands to appropriate icons ### Default IDE Setting - Add "Default IDE" selector in Settings > Account section - Options: Auto-detect (Cursor > VS Code > first available) or explicit choice - Setting persists via `defaultEditorCommand` in global settings ### Worktree Dropdown Improvements - Implement split-button UX for "Open In" action - Click main area: opens directly in default IDE (single click) - Click chevron: shows submenu with other editors + Copy Path - Each editor shows with its branded icon ## Type & Store Changes - Add `defaultEditorCommand: string | null` to GlobalSettings - Add to app-store with `setDefaultEditorCommand` action - Add to SETTINGS_FIELDS_TO_SYNC for persistence - Add `useAvailableEditors` hook for fetching detected editors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { createLogger } from '@automaker/utils/logger';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
|
||||
const logger = createLogger('AvailableEditors');
|
||||
|
||||
export interface EditorInfo {
|
||||
name: string;
|
||||
command: string;
|
||||
}
|
||||
|
||||
export function useAvailableEditors() {
|
||||
const [editors, setEditors] = useState<EditorInfo[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const fetchAvailableEditors = useCallback(async () => {
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.getAvailableEditors) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
const result = await api.worktree.getAvailableEditors();
|
||||
if (result.success && result.result?.editors) {
|
||||
setEditors(result.result.editors);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to fetch available editors:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAvailableEditors();
|
||||
}, [fetchAvailableEditors]);
|
||||
|
||||
return {
|
||||
editors,
|
||||
isLoading,
|
||||
// Convenience property: has multiple editors (for deciding whether to show submenu)
|
||||
hasMultipleEditors: editors.length > 1,
|
||||
// The first editor is the "default" one
|
||||
defaultEditor: editors[0] ?? null,
|
||||
};
|
||||
}
|
||||
@@ -125,14 +125,14 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
|
||||
[isPushing, fetchBranches, fetchWorktrees]
|
||||
);
|
||||
|
||||
const handleOpenInEditor = useCallback(async (worktree: WorktreeInfo) => {
|
||||
const handleOpenInEditor = useCallback(async (worktree: WorktreeInfo, editorCommand?: string) => {
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
if (!api?.worktree?.openInEditor) {
|
||||
logger.warn('Open in editor API not available');
|
||||
return;
|
||||
}
|
||||
const result = await api.worktree.openInEditor(worktree.path);
|
||||
const result = await api.worktree.openInEditor(worktree.path, editorCommand);
|
||||
if (result.success && result.result) {
|
||||
toast.success(result.result.message);
|
||||
} else if (result.error) {
|
||||
|
||||
Reference in New Issue
Block a user