mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 20:43:36 +00:00
Merge remote-tracking branch 'upstream/v0.13.0rc' into feat/react-query
# Conflicts: # apps/ui/src/components/views/board-view.tsx # apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx # apps/ui/src/components/views/board-view/hooks/use-board-features.ts # apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx # apps/ui/src/hooks/use-project-settings-loader.ts
This commit is contained in:
@@ -132,11 +132,12 @@ export function DevServerLogsPanel({
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
|
||||
<DialogContent
|
||||
className="w-[70vw] max-w-[900px] max-h-[85vh] flex flex-col gap-0 p-0 overflow-hidden"
|
||||
className="w-full h-full max-w-full max-h-full sm:w-[70vw] sm:max-w-[900px] sm:max-h-[85vh] sm:h-auto sm:rounded-xl rounded-none flex flex-col gap-0 p-0 overflow-hidden"
|
||||
data-testid="dev-server-logs-panel"
|
||||
compact
|
||||
>
|
||||
{/* Compact Header */}
|
||||
<DialogHeader className="shrink-0 px-4 py-3 border-b border-border/50">
|
||||
<DialogHeader className="shrink-0 px-4 py-3 border-b border-border/50 pr-12">
|
||||
<div className="flex items-center justify-between">
|
||||
<DialogTitle className="flex items-center gap-2 text-base">
|
||||
<Terminal className="w-4 h-4 text-primary" />
|
||||
|
||||
@@ -25,10 +25,13 @@ import {
|
||||
AlertCircle,
|
||||
RefreshCw,
|
||||
Copy,
|
||||
Eye,
|
||||
ScrollText,
|
||||
Terminal,
|
||||
SquarePlus,
|
||||
SplitSquareHorizontal,
|
||||
Zap,
|
||||
Undo2,
|
||||
} from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -56,12 +59,16 @@ interface WorktreeActionsDropdownProps {
|
||||
gitRepoStatus: GitRepoStatus;
|
||||
/** When true, renders as a standalone button (not attached to another element) */
|
||||
standalone?: boolean;
|
||||
/** Whether auto mode is running for this worktree */
|
||||
isAutoModeRunning?: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onPull: (worktree: WorktreeInfo) => void;
|
||||
onPush: (worktree: WorktreeInfo) => void;
|
||||
onOpenInEditor: (worktree: WorktreeInfo, editorCommand?: string) => void;
|
||||
onOpenInIntegratedTerminal: (worktree: WorktreeInfo, mode?: 'tab' | 'split') => void;
|
||||
onOpenInExternalTerminal: (worktree: WorktreeInfo, terminalId?: string) => void;
|
||||
onViewChanges: (worktree: WorktreeInfo) => void;
|
||||
onDiscardChanges: (worktree: WorktreeInfo) => void;
|
||||
onCommit: (worktree: WorktreeInfo) => void;
|
||||
onCreatePR: (worktree: WorktreeInfo) => void;
|
||||
onAddressPRComments: (worktree: WorktreeInfo, prInfo: PRInfo) => void;
|
||||
@@ -73,6 +80,7 @@ interface WorktreeActionsDropdownProps {
|
||||
onOpenDevServerUrl: (worktree: WorktreeInfo) => void;
|
||||
onViewDevServerLogs: (worktree: WorktreeInfo) => void;
|
||||
onRunInitScript: (worktree: WorktreeInfo) => void;
|
||||
onToggleAutoMode?: (worktree: WorktreeInfo) => void;
|
||||
hasInitScript: boolean;
|
||||
}
|
||||
|
||||
@@ -88,12 +96,15 @@ export function WorktreeActionsDropdown({
|
||||
devServerInfo,
|
||||
gitRepoStatus,
|
||||
standalone = false,
|
||||
isAutoModeRunning = false,
|
||||
onOpenChange,
|
||||
onPull,
|
||||
onPush,
|
||||
onOpenInEditor,
|
||||
onOpenInIntegratedTerminal,
|
||||
onOpenInExternalTerminal,
|
||||
onViewChanges,
|
||||
onDiscardChanges,
|
||||
onCommit,
|
||||
onCreatePR,
|
||||
onAddressPRComments,
|
||||
@@ -105,6 +116,7 @@ export function WorktreeActionsDropdown({
|
||||
onOpenDevServerUrl,
|
||||
onViewDevServerLogs,
|
||||
onRunInitScript,
|
||||
onToggleAutoMode,
|
||||
hasInitScript,
|
||||
}: WorktreeActionsDropdownProps) {
|
||||
// Get available editors for the "Open In" submenu
|
||||
@@ -214,6 +226,26 @@ export function WorktreeActionsDropdown({
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
{/* Auto Mode toggle */}
|
||||
{onToggleAutoMode && (
|
||||
<>
|
||||
{isAutoModeRunning ? (
|
||||
<DropdownMenuItem onClick={() => onToggleAutoMode(worktree)} className="text-xs">
|
||||
<span className="flex items-center mr-2">
|
||||
<Zap className="w-3.5 h-3.5 text-yellow-500" />
|
||||
<span className="ml-0.5 h-2 w-2 rounded-full bg-green-500 animate-pulse" />
|
||||
</span>
|
||||
Stop Auto Mode
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
<DropdownMenuItem onClick={() => onToggleAutoMode(worktree)} className="text-xs">
|
||||
<Zap className="w-3.5 h-3.5 mr-2" />
|
||||
Start Auto Mode
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
<TooltipWrapper showTooltip={!!gitOpsDisabledReason} tooltipContent={gitOpsDisabledReason}>
|
||||
<DropdownMenuItem
|
||||
onClick={() => canPerformGitOps && onPull(worktree)}
|
||||
@@ -408,6 +440,13 @@ export function WorktreeActionsDropdown({
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
{worktree.hasChanges && (
|
||||
<DropdownMenuItem onClick={() => onViewChanges(worktree)} className="text-xs">
|
||||
<Eye className="w-3.5 h-3.5 mr-2" />
|
||||
View Changes
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{worktree.hasChanges && (
|
||||
<TooltipWrapper
|
||||
showTooltip={!gitRepoStatus.isGitRepo}
|
||||
@@ -483,9 +522,30 @@ export function WorktreeActionsDropdown({
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
{worktree.hasChanges && (
|
||||
<TooltipWrapper
|
||||
showTooltip={!gitRepoStatus.isGitRepo}
|
||||
tooltipContent="Not a git repository"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
onClick={() => gitRepoStatus.isGitRepo && onDiscardChanges(worktree)}
|
||||
disabled={!gitRepoStatus.isGitRepo}
|
||||
className={cn(
|
||||
'text-xs text-destructive focus:text-destructive',
|
||||
!gitRepoStatus.isGitRepo && 'opacity-50 cursor-not-allowed'
|
||||
)}
|
||||
>
|
||||
<Undo2 className="w-3.5 h-3.5 mr-2" />
|
||||
Discard Changes
|
||||
{!gitRepoStatus.isGitRepo && (
|
||||
<AlertCircle className="w-3 h-3 ml-auto text-muted-foreground" />
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
</TooltipWrapper>
|
||||
)}
|
||||
{!worktree.isMain && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
onClick={() => onDeleteWorktree(worktree)}
|
||||
className="text-xs text-destructive focus:text-destructive"
|
||||
|
||||
@@ -29,6 +29,8 @@ interface WorktreeTabProps {
|
||||
aheadCount: number;
|
||||
behindCount: number;
|
||||
gitRepoStatus: GitRepoStatus;
|
||||
/** Whether auto mode is running for this worktree */
|
||||
isAutoModeRunning?: boolean;
|
||||
onSelectWorktree: (worktree: WorktreeInfo) => void;
|
||||
onBranchDropdownOpenChange: (open: boolean) => void;
|
||||
onActionsDropdownOpenChange: (open: boolean) => void;
|
||||
@@ -40,6 +42,8 @@ interface WorktreeTabProps {
|
||||
onOpenInEditor: (worktree: WorktreeInfo, editorCommand?: string) => void;
|
||||
onOpenInIntegratedTerminal: (worktree: WorktreeInfo, mode?: 'tab' | 'split') => void;
|
||||
onOpenInExternalTerminal: (worktree: WorktreeInfo, terminalId?: string) => void;
|
||||
onViewChanges: (worktree: WorktreeInfo) => void;
|
||||
onDiscardChanges: (worktree: WorktreeInfo) => void;
|
||||
onCommit: (worktree: WorktreeInfo) => void;
|
||||
onCreatePR: (worktree: WorktreeInfo) => void;
|
||||
onAddressPRComments: (worktree: WorktreeInfo, prInfo: PRInfo) => void;
|
||||
@@ -51,6 +55,7 @@ interface WorktreeTabProps {
|
||||
onOpenDevServerUrl: (worktree: WorktreeInfo) => void;
|
||||
onViewDevServerLogs: (worktree: WorktreeInfo) => void;
|
||||
onRunInitScript: (worktree: WorktreeInfo) => void;
|
||||
onToggleAutoMode?: (worktree: WorktreeInfo) => void;
|
||||
hasInitScript: boolean;
|
||||
}
|
||||
|
||||
@@ -75,6 +80,7 @@ export function WorktreeTab({
|
||||
aheadCount,
|
||||
behindCount,
|
||||
gitRepoStatus,
|
||||
isAutoModeRunning = false,
|
||||
onSelectWorktree,
|
||||
onBranchDropdownOpenChange,
|
||||
onActionsDropdownOpenChange,
|
||||
@@ -86,6 +92,8 @@ export function WorktreeTab({
|
||||
onOpenInEditor,
|
||||
onOpenInIntegratedTerminal,
|
||||
onOpenInExternalTerminal,
|
||||
onViewChanges,
|
||||
onDiscardChanges,
|
||||
onCommit,
|
||||
onCreatePR,
|
||||
onAddressPRComments,
|
||||
@@ -97,6 +105,7 @@ export function WorktreeTab({
|
||||
onOpenDevServerUrl,
|
||||
onViewDevServerLogs,
|
||||
onRunInitScript,
|
||||
onToggleAutoMode,
|
||||
hasInitScript,
|
||||
}: WorktreeTabProps) {
|
||||
let prBadge: JSX.Element | null = null;
|
||||
@@ -332,6 +341,26 @@ export function WorktreeTab({
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
{isAutoModeRunning && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className={cn(
|
||||
'flex items-center justify-center h-7 px-1.5 rounded-none border-r-0',
|
||||
isSelected ? 'bg-primary text-primary-foreground' : 'bg-secondary/50'
|
||||
)}
|
||||
>
|
||||
<span className="h-2 w-2 rounded-full bg-green-500 animate-pulse" />
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Auto Mode Running</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
<WorktreeActionsDropdown
|
||||
worktree={worktree}
|
||||
isSelected={isSelected}
|
||||
@@ -343,12 +372,15 @@ export function WorktreeTab({
|
||||
isDevServerRunning={isDevServerRunning}
|
||||
devServerInfo={devServerInfo}
|
||||
gitRepoStatus={gitRepoStatus}
|
||||
isAutoModeRunning={isAutoModeRunning}
|
||||
onOpenChange={onActionsDropdownOpenChange}
|
||||
onPull={onPull}
|
||||
onPush={onPush}
|
||||
onOpenInEditor={onOpenInEditor}
|
||||
onOpenInIntegratedTerminal={onOpenInIntegratedTerminal}
|
||||
onOpenInExternalTerminal={onOpenInExternalTerminal}
|
||||
onViewChanges={onViewChanges}
|
||||
onDiscardChanges={onDiscardChanges}
|
||||
onCommit={onCommit}
|
||||
onCreatePR={onCreatePR}
|
||||
onAddressPRComments={onAddressPRComments}
|
||||
@@ -360,6 +392,7 @@ export function WorktreeTab({
|
||||
onOpenDevServerUrl={onOpenDevServerUrl}
|
||||
onViewDevServerLogs={onViewDevServerLogs}
|
||||
onRunInitScript={onRunInitScript}
|
||||
onToggleAutoMode={onToggleAutoMode}
|
||||
hasInitScript={hasInitScript}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useRef, useCallback, useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { GitBranch, Plus, RefreshCw } from 'lucide-react';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import { cn, pathsEqual } from '@/lib/utils';
|
||||
import { pathsEqual } from '@/lib/utils';
|
||||
import { toast } from 'sonner';
|
||||
import { getHttpApiClient } from '@/lib/http-api-client';
|
||||
import { useIsMobile } from '@/hooks/use-media-query';
|
||||
@@ -22,6 +22,10 @@ import {
|
||||
WorktreeActionsDropdown,
|
||||
BranchSwitchDropdown,
|
||||
} from './components';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { ViewWorktreeChangesDialog } from '../dialogs';
|
||||
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
import { Undo2 } from 'lucide-react';
|
||||
|
||||
export function WorktreePanel({
|
||||
projectPath,
|
||||
@@ -51,7 +55,6 @@ export function WorktreePanel({
|
||||
|
||||
const {
|
||||
isStartingDevServer,
|
||||
getWorktreeKey,
|
||||
isDevServerRunning,
|
||||
getDevServerInfo,
|
||||
handleStartDevServer,
|
||||
@@ -90,10 +93,79 @@ export function WorktreePanel({
|
||||
features,
|
||||
});
|
||||
|
||||
// Auto-mode state management using the store
|
||||
// Use separate selectors to avoid creating new object references on each render
|
||||
const autoModeByWorktree = useAppStore((state) => state.autoModeByWorktree);
|
||||
const currentProject = useAppStore((state) => state.currentProject);
|
||||
|
||||
// Helper to generate worktree key for auto-mode (inlined to avoid selector issues)
|
||||
const getAutoModeWorktreeKey = useCallback(
|
||||
(projectId: string, branchName: string | null): string => {
|
||||
return `${projectId}::${branchName ?? '__main__'}`;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Helper to check if auto-mode is running for a specific worktree
|
||||
const isAutoModeRunningForWorktree = useCallback(
|
||||
(worktree: WorktreeInfo): boolean => {
|
||||
if (!currentProject) return false;
|
||||
const branchName = worktree.isMain ? null : worktree.branch;
|
||||
const key = getAutoModeWorktreeKey(currentProject.id, branchName);
|
||||
return autoModeByWorktree[key]?.isRunning ?? false;
|
||||
},
|
||||
[currentProject, autoModeByWorktree, getAutoModeWorktreeKey]
|
||||
);
|
||||
|
||||
// Handler to toggle auto-mode for a worktree
|
||||
const handleToggleAutoMode = useCallback(
|
||||
async (worktree: WorktreeInfo) => {
|
||||
if (!currentProject) return;
|
||||
|
||||
// Import the useAutoMode to get start/stop functions
|
||||
// Since useAutoMode is a hook, we'll use the API client directly
|
||||
const api = getHttpApiClient();
|
||||
const branchName = worktree.isMain ? null : worktree.branch;
|
||||
const isRunning = isAutoModeRunningForWorktree(worktree);
|
||||
|
||||
try {
|
||||
if (isRunning) {
|
||||
const result = await api.autoMode.stop(projectPath, branchName);
|
||||
if (result.success) {
|
||||
const desc = branchName ? `worktree ${branchName}` : 'main branch';
|
||||
toast.success(`Auto Mode stopped for ${desc}`);
|
||||
} else {
|
||||
toast.error(result.error || 'Failed to stop Auto Mode');
|
||||
}
|
||||
} else {
|
||||
const result = await api.autoMode.start(projectPath, branchName);
|
||||
if (result.success) {
|
||||
const desc = branchName ? `worktree ${branchName}` : 'main branch';
|
||||
toast.success(`Auto Mode started for ${desc}`);
|
||||
} else {
|
||||
toast.error(result.error || 'Failed to start Auto Mode');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Error toggling Auto Mode');
|
||||
console.error('Auto mode toggle error:', error);
|
||||
}
|
||||
},
|
||||
[currentProject, projectPath, isAutoModeRunningForWorktree]
|
||||
);
|
||||
|
||||
// Check if init script exists for the project using React Query
|
||||
const { data: initScriptData } = useWorktreeInitScript(projectPath);
|
||||
const hasInitScript = initScriptData?.exists ?? false;
|
||||
|
||||
// View changes dialog state
|
||||
const [viewChangesDialogOpen, setViewChangesDialogOpen] = useState(false);
|
||||
const [viewChangesWorktree, setViewChangesWorktree] = useState<WorktreeInfo | null>(null);
|
||||
|
||||
// Discard changes confirmation dialog state
|
||||
const [discardChangesDialogOpen, setDiscardChangesDialogOpen] = useState(false);
|
||||
const [discardChangesWorktree, setDiscardChangesWorktree] = useState<WorktreeInfo | null>(null);
|
||||
|
||||
// Log panel state management
|
||||
const [logPanelOpen, setLogPanelOpen] = useState(false);
|
||||
const [logPanelWorktree, setLogPanelWorktree] = useState<WorktreeInfo | null>(null);
|
||||
@@ -161,6 +233,41 @@ export function WorktreePanel({
|
||||
[projectPath]
|
||||
);
|
||||
|
||||
const handleViewChanges = useCallback((worktree: WorktreeInfo) => {
|
||||
setViewChangesWorktree(worktree);
|
||||
setViewChangesDialogOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleDiscardChanges = useCallback((worktree: WorktreeInfo) => {
|
||||
setDiscardChangesWorktree(worktree);
|
||||
setDiscardChangesDialogOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleConfirmDiscardChanges = useCallback(async () => {
|
||||
if (!discardChangesWorktree) return;
|
||||
|
||||
try {
|
||||
const api = getHttpApiClient();
|
||||
const result = await api.worktree.discardChanges(discardChangesWorktree.path);
|
||||
|
||||
if (result.success) {
|
||||
toast.success('Changes discarded', {
|
||||
description: `Discarded changes in ${discardChangesWorktree.branch}`,
|
||||
});
|
||||
// Refresh worktrees to update the changes status
|
||||
fetchWorktrees({ silent: true });
|
||||
} else {
|
||||
toast.error('Failed to discard changes', {
|
||||
description: result.error || 'Unknown error',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Failed to discard changes', {
|
||||
description: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
}
|
||||
}, [discardChangesWorktree, fetchWorktrees]);
|
||||
|
||||
// Handle opening the log panel for a specific worktree
|
||||
const handleViewDevServerLogs = useCallback((worktree: WorktreeInfo) => {
|
||||
setLogPanelWorktree(worktree);
|
||||
@@ -224,12 +331,15 @@ export function WorktreePanel({
|
||||
isDevServerRunning={isDevServerRunning(selectedWorktree)}
|
||||
devServerInfo={getDevServerInfo(selectedWorktree)}
|
||||
gitRepoStatus={gitRepoStatus}
|
||||
isAutoModeRunning={isAutoModeRunningForWorktree(selectedWorktree)}
|
||||
onOpenChange={handleActionsDropdownOpenChange(selectedWorktree)}
|
||||
onPull={handlePull}
|
||||
onPush={handlePush}
|
||||
onOpenInEditor={handleOpenInEditor}
|
||||
onOpenInIntegratedTerminal={handleOpenInIntegratedTerminal}
|
||||
onOpenInExternalTerminal={handleOpenInExternalTerminal}
|
||||
onViewChanges={handleViewChanges}
|
||||
onDiscardChanges={handleDiscardChanges}
|
||||
onCommit={onCommit}
|
||||
onCreatePR={onCreatePR}
|
||||
onAddressPRComments={onAddressPRComments}
|
||||
@@ -241,6 +351,7 @@ export function WorktreePanel({
|
||||
onOpenDevServerUrl={handleOpenDevServerUrl}
|
||||
onViewDevServerLogs={handleViewDevServerLogs}
|
||||
onRunInitScript={handleRunInitScript}
|
||||
onToggleAutoMode={handleToggleAutoMode}
|
||||
hasInitScript={hasInitScript}
|
||||
/>
|
||||
)}
|
||||
@@ -274,6 +385,36 @@ export function WorktreePanel({
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* View Changes Dialog */}
|
||||
<ViewWorktreeChangesDialog
|
||||
open={viewChangesDialogOpen}
|
||||
onOpenChange={setViewChangesDialogOpen}
|
||||
worktree={viewChangesWorktree}
|
||||
projectPath={projectPath}
|
||||
/>
|
||||
|
||||
{/* Discard Changes Confirmation Dialog */}
|
||||
<ConfirmDialog
|
||||
open={discardChangesDialogOpen}
|
||||
onOpenChange={setDiscardChangesDialogOpen}
|
||||
onConfirm={handleConfirmDiscardChanges}
|
||||
title="Discard Changes"
|
||||
description={`Are you sure you want to discard all changes in "${discardChangesWorktree?.branch}"? This will reset staged changes, discard modifications to tracked files, and remove untracked files. This action cannot be undone.`}
|
||||
icon={Undo2}
|
||||
iconClassName="text-destructive"
|
||||
confirmText="Discard Changes"
|
||||
confirmVariant="destructive"
|
||||
/>
|
||||
|
||||
{/* Dev Server Logs Panel */}
|
||||
<DevServerLogsPanel
|
||||
open={logPanelOpen}
|
||||
onClose={handleCloseLogPanel}
|
||||
worktree={logPanelWorktree}
|
||||
onStopDevServer={handleStopDevServer}
|
||||
onOpenDevServerUrl={handleOpenDevServerUrl}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -308,6 +449,7 @@ export function WorktreePanel({
|
||||
aheadCount={aheadCount}
|
||||
behindCount={behindCount}
|
||||
gitRepoStatus={gitRepoStatus}
|
||||
isAutoModeRunning={isAutoModeRunningForWorktree(mainWorktree)}
|
||||
onSelectWorktree={handleSelectWorktree}
|
||||
onBranchDropdownOpenChange={handleBranchDropdownOpenChange(mainWorktree)}
|
||||
onActionsDropdownOpenChange={handleActionsDropdownOpenChange(mainWorktree)}
|
||||
@@ -319,6 +461,8 @@ export function WorktreePanel({
|
||||
onOpenInEditor={handleOpenInEditor}
|
||||
onOpenInIntegratedTerminal={handleOpenInIntegratedTerminal}
|
||||
onOpenInExternalTerminal={handleOpenInExternalTerminal}
|
||||
onViewChanges={handleViewChanges}
|
||||
onDiscardChanges={handleDiscardChanges}
|
||||
onCommit={onCommit}
|
||||
onCreatePR={onCreatePR}
|
||||
onAddressPRComments={onAddressPRComments}
|
||||
@@ -330,6 +474,7 @@ export function WorktreePanel({
|
||||
onOpenDevServerUrl={handleOpenDevServerUrl}
|
||||
onViewDevServerLogs={handleViewDevServerLogs}
|
||||
onRunInitScript={handleRunInitScript}
|
||||
onToggleAutoMode={handleToggleAutoMode}
|
||||
hasInitScript={hasInitScript}
|
||||
/>
|
||||
)}
|
||||
@@ -368,6 +513,7 @@ export function WorktreePanel({
|
||||
aheadCount={aheadCount}
|
||||
behindCount={behindCount}
|
||||
gitRepoStatus={gitRepoStatus}
|
||||
isAutoModeRunning={isAutoModeRunningForWorktree(worktree)}
|
||||
onSelectWorktree={handleSelectWorktree}
|
||||
onBranchDropdownOpenChange={handleBranchDropdownOpenChange(worktree)}
|
||||
onActionsDropdownOpenChange={handleActionsDropdownOpenChange(worktree)}
|
||||
@@ -379,6 +525,8 @@ export function WorktreePanel({
|
||||
onOpenInEditor={handleOpenInEditor}
|
||||
onOpenInIntegratedTerminal={handleOpenInIntegratedTerminal}
|
||||
onOpenInExternalTerminal={handleOpenInExternalTerminal}
|
||||
onViewChanges={handleViewChanges}
|
||||
onDiscardChanges={handleDiscardChanges}
|
||||
onCommit={onCommit}
|
||||
onCreatePR={onCreatePR}
|
||||
onAddressPRComments={onAddressPRComments}
|
||||
@@ -390,6 +538,7 @@ export function WorktreePanel({
|
||||
onOpenDevServerUrl={handleOpenDevServerUrl}
|
||||
onViewDevServerLogs={handleViewDevServerLogs}
|
||||
onRunInitScript={handleRunInitScript}
|
||||
onToggleAutoMode={handleToggleAutoMode}
|
||||
hasInitScript={hasInitScript}
|
||||
/>
|
||||
);
|
||||
@@ -424,6 +573,27 @@ export function WorktreePanel({
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* View Changes Dialog */}
|
||||
<ViewWorktreeChangesDialog
|
||||
open={viewChangesDialogOpen}
|
||||
onOpenChange={setViewChangesDialogOpen}
|
||||
worktree={viewChangesWorktree}
|
||||
projectPath={projectPath}
|
||||
/>
|
||||
|
||||
{/* Discard Changes Confirmation Dialog */}
|
||||
<ConfirmDialog
|
||||
open={discardChangesDialogOpen}
|
||||
onOpenChange={setDiscardChangesDialogOpen}
|
||||
onConfirm={handleConfirmDiscardChanges}
|
||||
title="Discard Changes"
|
||||
description={`Are you sure you want to discard all changes in "${discardChangesWorktree?.branch}"? This will reset staged changes, discard modifications to tracked files, and remove untracked files. This action cannot be undone.`}
|
||||
icon={Undo2}
|
||||
iconClassName="text-destructive"
|
||||
confirmText="Discard Changes"
|
||||
confirmVariant="destructive"
|
||||
/>
|
||||
|
||||
{/* Dev Server Logs Panel */}
|
||||
<DevServerLogsPanel
|
||||
open={logPanelOpen}
|
||||
|
||||
Reference in New Issue
Block a user