mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
fixing some bugs
This commit is contained in:
@@ -67,6 +67,8 @@ export function BoardView() {
|
||||
setSpecCreatingForProject,
|
||||
getCurrentWorktree,
|
||||
setCurrentWorktree,
|
||||
getWorktrees,
|
||||
setWorktrees,
|
||||
} = useAppStore();
|
||||
const shortcuts = useKeyboardShortcutsConfig();
|
||||
const {
|
||||
@@ -215,7 +217,7 @@ export function BoardView() {
|
||||
// Branch suggestions for the branch autocomplete
|
||||
const [branchSuggestions, setBranchSuggestions] = useState<string[]>([]);
|
||||
|
||||
// Fetch branches when project changes
|
||||
// Fetch branches when project changes or worktrees are created/modified
|
||||
useEffect(() => {
|
||||
const fetchBranches = async () => {
|
||||
if (!currentProject) {
|
||||
@@ -244,7 +246,7 @@ export function BoardView() {
|
||||
};
|
||||
|
||||
fetchBranches();
|
||||
}, [currentProject]);
|
||||
}, [currentProject, worktreeRefreshKey]);
|
||||
|
||||
// Custom collision detection that prioritizes columns over cards
|
||||
const collisionDetectionStrategy = useCallback(
|
||||
@@ -339,16 +341,21 @@ export function BoardView() {
|
||||
});
|
||||
|
||||
// Use drag and drop hook
|
||||
// Get current worktree path and branch for filtering features
|
||||
const currentWorktreePath = currentProject ? getCurrentWorktree(currentProject.path) : null;
|
||||
// Get current worktree info (path and branch) for filtering features
|
||||
const currentWorktreeInfo = currentProject ? getCurrentWorktree(currentProject.path) : null;
|
||||
const currentWorktreePath = currentWorktreeInfo?.path ?? null;
|
||||
const currentWorktreeBranch = currentWorktreeInfo?.branch ?? null;
|
||||
const worktreesByProject = useAppStore((s) => s.worktreesByProject);
|
||||
const worktrees = useMemo(
|
||||
() => (currentProject ? (worktreesByProject[currentProject.path] ?? EMPTY_WORKTREES) : EMPTY_WORKTREES),
|
||||
[currentProject, worktreesByProject]
|
||||
);
|
||||
const currentWorktreeBranch = currentWorktreePath
|
||||
? worktrees.find(w => w.path === currentWorktreePath)?.branch || null
|
||||
: null;
|
||||
|
||||
// Get the branch for the currently selected worktree (for defaulting new features)
|
||||
// Use the branch from currentWorktreeInfo, or fall back to main worktree's branch
|
||||
const selectedWorktreeBranch = currentWorktreeBranch
|
||||
|| worktrees.find(w => w.isMain)?.branch
|
||||
|| "main";
|
||||
|
||||
const { activeFeature, handleDragStart, handleDragEnd } = useBoardDragDrop({
|
||||
features: hookFeatures,
|
||||
@@ -533,6 +540,7 @@ export function BoardView() {
|
||||
categorySuggestions={categorySuggestions}
|
||||
branchSuggestions={branchSuggestions}
|
||||
defaultSkipTests={defaultSkipTests}
|
||||
defaultBranch={selectedWorktreeBranch}
|
||||
isMaximized={isMaximized}
|
||||
showProfilesOnly={showProfilesOnly}
|
||||
aiProfiles={aiProfiles}
|
||||
@@ -603,10 +611,24 @@ export function BoardView() {
|
||||
open={showCreateWorktreeDialog}
|
||||
onOpenChange={setShowCreateWorktreeDialog}
|
||||
projectPath={currentProject.path}
|
||||
onCreated={(worktreePath) => {
|
||||
onCreated={(newWorktree) => {
|
||||
// Add the new worktree to the store immediately to avoid race condition
|
||||
// when deriving currentWorktreeBranch for filtering
|
||||
const currentWorktrees = getWorktrees(currentProject.path);
|
||||
const newWorktreeInfo = {
|
||||
path: newWorktree.path,
|
||||
branch: newWorktree.branch,
|
||||
isMain: false,
|
||||
isCurrent: false,
|
||||
hasWorktree: true,
|
||||
};
|
||||
setWorktrees(currentProject.path, [...currentWorktrees, newWorktreeInfo]);
|
||||
|
||||
// Now set the current worktree with both path and branch
|
||||
setCurrentWorktree(currentProject.path, newWorktree.path, newWorktree.branch);
|
||||
|
||||
// Trigger refresh to get full worktree details (hasChanges, etc.)
|
||||
setWorktreeRefreshKey((k) => k + 1);
|
||||
// Auto-select the newly created worktree
|
||||
setCurrentWorktree(currentProject.path, worktreePath);
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
@@ -198,13 +198,15 @@ export function WorktreeSelector({
|
||||
// Initialize selection to main if not set
|
||||
useEffect(() => {
|
||||
if (worktrees.length > 0 && currentWorktree === undefined) {
|
||||
setCurrentWorktree(projectPath, null); // null = main worktree
|
||||
const mainWorktree = worktrees.find(w => w.isMain);
|
||||
const mainBranch = mainWorktree?.branch || "main";
|
||||
setCurrentWorktree(projectPath, null, mainBranch); // null = main worktree
|
||||
}
|
||||
}, [worktrees, currentWorktree, projectPath, setCurrentWorktree]);
|
||||
|
||||
const handleSelectWorktree = async (worktree: WorktreeInfo) => {
|
||||
// Simply select the worktree in the UI
|
||||
setCurrentWorktree(projectPath, worktree.isMain ? null : worktree.path);
|
||||
// Simply select the worktree in the UI with both path and branch
|
||||
setCurrentWorktree(projectPath, worktree.isMain ? null : worktree.path, worktree.branch);
|
||||
};
|
||||
|
||||
const handleStartDevServer = async (worktree: WorktreeInfo) => {
|
||||
@@ -454,19 +456,20 @@ export function WorktreeSelector({
|
||||
};
|
||||
|
||||
// The "selected" worktree is based on UI state, not git's current branch
|
||||
// currentWorktree is null for main, or the worktree path for others
|
||||
const selectedWorktree = currentWorktree
|
||||
? worktrees.find((w) => w.path === currentWorktree)
|
||||
// currentWorktree.path is null for main, or the worktree path for others
|
||||
const currentWorktreePath = currentWorktree?.path ?? null;
|
||||
const selectedWorktree = currentWorktreePath
|
||||
? worktrees.find((w) => w.path === currentWorktreePath)
|
||||
: worktrees.find((w) => w.isMain);
|
||||
|
||||
|
||||
// Render a worktree tab with branch selector (for main) and actions dropdown
|
||||
const renderWorktreeTab = (worktree: WorktreeInfo) => {
|
||||
// Selection is based on UI state, not git's current branch
|
||||
// Default to main selected if currentWorktree is null or undefined
|
||||
// Default to main selected if currentWorktree is null/undefined or path is null
|
||||
const isSelected = worktree.isMain
|
||||
? currentWorktree === null || currentWorktree === undefined
|
||||
: worktree.path === currentWorktree;
|
||||
? currentWorktree === null || currentWorktree === undefined || currentWorktree.path === null
|
||||
: worktree.path === currentWorktreePath;
|
||||
|
||||
const isRunning = hasRunningFeatures(worktree);
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ interface AddFeatureDialogProps {
|
||||
categorySuggestions: string[];
|
||||
branchSuggestions: string[];
|
||||
defaultSkipTests: boolean;
|
||||
defaultBranch?: string;
|
||||
isMaximized: boolean;
|
||||
showProfilesOnly: boolean;
|
||||
aiProfiles: AIProfile[];
|
||||
@@ -81,6 +82,7 @@ export function AddFeatureDialog({
|
||||
categorySuggestions,
|
||||
branchSuggestions,
|
||||
defaultSkipTests,
|
||||
defaultBranch = "main",
|
||||
isMaximized,
|
||||
showProfilesOnly,
|
||||
aiProfiles,
|
||||
@@ -109,15 +111,16 @@ export function AddFeatureDialog({
|
||||
// Get enhancement model from store
|
||||
const { enhancementModel } = useAppStore();
|
||||
|
||||
// Sync skipTests default when dialog opens
|
||||
// Sync defaults when dialog opens
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setNewFeature((prev) => ({
|
||||
...prev,
|
||||
skipTests: defaultSkipTests,
|
||||
branchName: defaultBranch,
|
||||
}));
|
||||
}
|
||||
}, [open, defaultSkipTests]);
|
||||
}, [open, defaultSkipTests, defaultBranch]);
|
||||
|
||||
const handleAdd = () => {
|
||||
if (!newFeature.description.trim()) {
|
||||
@@ -155,7 +158,7 @@ export function AddFeatureDialog({
|
||||
model: "opus",
|
||||
priority: 2,
|
||||
thinkingLevel: "none",
|
||||
branchName: "main",
|
||||
branchName: defaultBranch,
|
||||
});
|
||||
setNewFeaturePreviewMap(new Map());
|
||||
setShowAdvancedOptions(false);
|
||||
|
||||
@@ -16,11 +16,16 @@ import { GitBranch, Loader2 } from "lucide-react";
|
||||
import { getElectronAPI } from "@/lib/electron";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface CreatedWorktreeInfo {
|
||||
path: string;
|
||||
branch: string;
|
||||
}
|
||||
|
||||
interface CreateWorktreeDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
projectPath: string;
|
||||
onCreated: (worktreePath: string) => void;
|
||||
onCreated: (worktree: CreatedWorktreeInfo) => void;
|
||||
}
|
||||
|
||||
export function CreateWorktreeDialog({
|
||||
@@ -68,7 +73,7 @@ export function CreateWorktreeDialog({
|
||||
: "Using existing branch",
|
||||
}
|
||||
);
|
||||
onCreated(result.worktree.path);
|
||||
onCreated({ path: result.worktree.path, branch: result.worktree.branch });
|
||||
onOpenChange(false);
|
||||
setBranchName("");
|
||||
} else {
|
||||
|
||||
@@ -43,7 +43,12 @@ export function useBoardColumnFeatures({
|
||||
// Determine the effective worktree path and branch for filtering
|
||||
// If currentWorktreePath is null, we're on the main worktree
|
||||
const effectiveWorktreePath = currentWorktreePath || projectPath;
|
||||
const effectiveBranch = currentWorktreeBranch || "main";
|
||||
// Use the branch name from the selected worktree
|
||||
// If we're selecting main (currentWorktreePath is null), currentWorktreeBranch
|
||||
// should contain the main branch's actual name, defaulting to "main"
|
||||
// If we're selecting a non-main worktree but can't find it, currentWorktreeBranch is null
|
||||
// In that case, we can't do branch-based filtering, so we'll handle it specially below
|
||||
const effectiveBranch = currentWorktreeBranch;
|
||||
|
||||
filteredFeatures.forEach((f) => {
|
||||
// If feature has a running agent, always show it in "in_progress"
|
||||
@@ -62,6 +67,11 @@ export function useBoardColumnFeatures({
|
||||
} else if (f.worktreePath) {
|
||||
// Has worktreePath - match by path
|
||||
matchesWorktree = f.worktreePath === effectiveWorktreePath;
|
||||
} else if (effectiveBranch === null) {
|
||||
// We're selecting a non-main worktree but can't determine its branch yet
|
||||
// (worktrees haven't loaded). Don't show branch-only features until we know.
|
||||
// This prevents showing wrong features during loading.
|
||||
matchesWorktree = false;
|
||||
} else {
|
||||
// Has branchName but no worktreePath - match by branch name
|
||||
matchesWorktree = featureBranch === effectiveBranch;
|
||||
@@ -76,10 +86,12 @@ export function useBoardColumnFeatures({
|
||||
// Otherwise, use the feature's status (fallback to backlog for unknown statuses)
|
||||
const status = f.status as ColumnId;
|
||||
|
||||
// Backlog items are always visible (they have no worktree assigned)
|
||||
// For other statuses, filter by worktree
|
||||
// Filter all items by worktree, including backlog
|
||||
// This ensures backlog items with a branch assigned only show in that branch
|
||||
if (status === "backlog") {
|
||||
map.backlog.push(f);
|
||||
if (matchesWorktree) {
|
||||
map.backlog.push(f);
|
||||
}
|
||||
} else if (map[status]) {
|
||||
// Only show if matches current worktree or has no worktree assigned
|
||||
if (matchesWorktree) {
|
||||
|
||||
@@ -399,7 +399,8 @@ export interface AppState {
|
||||
useWorktrees: boolean; // Whether to use git worktree isolation for features (default: false)
|
||||
|
||||
// User-managed Worktrees (per-project)
|
||||
currentWorktreeByProject: Record<string, string | null>; // projectPath -> worktreePath or null for main
|
||||
// projectPath -> { path: worktreePath or null for main, branch: branch name }
|
||||
currentWorktreeByProject: Record<string, { path: string | null; branch: string }>;
|
||||
worktreesByProject: Record<
|
||||
string,
|
||||
Array<{
|
||||
@@ -582,7 +583,7 @@ export interface AppActions {
|
||||
|
||||
// Worktree Settings actions
|
||||
setUseWorktrees: (enabled: boolean) => void;
|
||||
setCurrentWorktree: (projectPath: string, worktreePath: string | null) => void;
|
||||
setCurrentWorktree: (projectPath: string, worktreePath: string | null, branch: string) => void;
|
||||
setWorktrees: (
|
||||
projectPath: string,
|
||||
worktrees: Array<{
|
||||
@@ -593,7 +594,7 @@ export interface AppActions {
|
||||
changedFilesCount?: number;
|
||||
}>
|
||||
) => void;
|
||||
getCurrentWorktree: (projectPath: string) => string | null;
|
||||
getCurrentWorktree: (projectPath: string) => { path: string | null; branch: string } | null;
|
||||
getWorktrees: (projectPath: string) => Array<{
|
||||
path: string;
|
||||
branch: string;
|
||||
@@ -1344,12 +1345,12 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
// Worktree Settings actions
|
||||
setUseWorktrees: (enabled) => set({ useWorktrees: enabled }),
|
||||
|
||||
setCurrentWorktree: (projectPath, worktreePath) => {
|
||||
setCurrentWorktree: (projectPath, worktreePath, branch) => {
|
||||
const current = get().currentWorktreeByProject;
|
||||
set({
|
||||
currentWorktreeByProject: {
|
||||
...current,
|
||||
[projectPath]: worktreePath,
|
||||
[projectPath]: { path: worktreePath, branch },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user