mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-24 00:13:07 +00:00
fix: Address code review comments
This commit is contained in:
@@ -174,6 +174,7 @@ export function CherryPickDialog({
|
||||
setCommitsError(null);
|
||||
setCommitLimit(30);
|
||||
setHasMoreCommits(false);
|
||||
setLoadingBranches(false);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
@@ -321,9 +322,7 @@ export function CherryPickDialog({
|
||||
} else {
|
||||
// Check for conflicts
|
||||
const errorMessage = result.error || '';
|
||||
const hasConflicts =
|
||||
errorMessage.toLowerCase().includes('conflict') ||
|
||||
(result as { hasConflicts?: boolean }).hasConflicts;
|
||||
const hasConflicts = errorMessage.toLowerCase().includes('conflict') || result.hasConflicts;
|
||||
|
||||
if (hasConflicts && onCreateConflictResolutionFeature) {
|
||||
setConflictInfo({
|
||||
@@ -333,7 +332,7 @@ export function CherryPickDialog({
|
||||
});
|
||||
setStep('conflict');
|
||||
toast.error('Cherry-pick conflicts detected', {
|
||||
description: 'The cherry-pick has conflicts that need to be resolved.',
|
||||
description: 'The cherry-pick was aborted due to conflicts. No changes were applied.',
|
||||
});
|
||||
} else {
|
||||
toast.error('Cherry-pick failed', {
|
||||
@@ -359,7 +358,7 @@ export function CherryPickDialog({
|
||||
});
|
||||
setStep('conflict');
|
||||
toast.error('Cherry-pick conflicts detected', {
|
||||
description: 'The cherry-pick has conflicts that need to be resolved.',
|
||||
description: 'The cherry-pick was aborted due to conflicts. No changes were applied.',
|
||||
});
|
||||
} else {
|
||||
toast.error('Cherry-pick failed', {
|
||||
@@ -469,7 +468,7 @@ export function CherryPickDialog({
|
||||
<DialogContent className="w-full h-full max-w-full max-h-full sm:w-[90vw] sm:max-w-[640px] sm:max-h-[100dvh] sm:h-auto sm:rounded-xl rounded-none flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Cherry className="w-5 h-5 text-black dark:text-black" />
|
||||
<Cherry className="w-5 h-5 text-foreground" />
|
||||
Cherry Pick Commits
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
@@ -673,7 +672,7 @@ export function CherryPickDialog({
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Cherry className="w-5 h-5 text-black dark:text-black" />
|
||||
<Cherry className="w-5 h-5 text-foreground" />
|
||||
Cherry Pick
|
||||
</DialogTitle>
|
||||
<DialogDescription asChild>
|
||||
|
||||
@@ -407,7 +407,7 @@ export function CommitWorktreeDialog({
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (
|
||||
e.key === 'Enter' &&
|
||||
e.metaKey &&
|
||||
(e.metaKey || e.ctrlKey) &&
|
||||
!isLoading &&
|
||||
!isGenerating &&
|
||||
message.trim() &&
|
||||
@@ -658,7 +658,8 @@ export function CommitWorktreeDialog({
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Press <kbd className="px-1 py-0.5 bg-muted rounded text-xs">Cmd+Enter</kbd> to commit
|
||||
Press <kbd className="px-1 py-0.5 bg-muted rounded text-xs">Cmd/Ctrl+Enter</kbd> to
|
||||
commit
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -78,9 +78,13 @@ export function CreateBranchDialog({
|
||||
|
||||
if (result.success && result.result) {
|
||||
setBranches(result.result.branches);
|
||||
// Default to current branch
|
||||
if (result.result.currentBranch) {
|
||||
setBaseBranch(result.result.currentBranch);
|
||||
// Only set the default base branch if no branch is currently selected,
|
||||
// or if the currently selected branch is no longer present in the fetched list
|
||||
const branchNames = result.result.branches.map((b: BranchInfo) => b.name);
|
||||
if (!baseBranch || !branchNames.includes(baseBranch)) {
|
||||
if (result.result.currentBranch) {
|
||||
setBaseBranch(result.result.currentBranch);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -88,7 +92,7 @@ export function CreateBranchDialog({
|
||||
} finally {
|
||||
setIsLoadingBranches(false);
|
||||
}
|
||||
}, [worktree]);
|
||||
}, [worktree, baseBranch]);
|
||||
|
||||
// Reset state and fetch branches when dialog opens
|
||||
useEffect(() => {
|
||||
|
||||
@@ -75,6 +75,12 @@ export function CreatePRDialog({
|
||||
const [remotes, setRemotes] = useState<RemoteInfo[]>([]);
|
||||
const [selectedRemote, setSelectedRemote] = useState<string>('');
|
||||
const [isLoadingRemotes, setIsLoadingRemotes] = useState(false);
|
||||
// Keep a ref in sync with selectedRemote so fetchRemotes can read the latest value
|
||||
// without needing it in its dependency array (which would cause re-fetch loops)
|
||||
const selectedRemoteRef = useRef<string>(selectedRemote);
|
||||
useEffect(() => {
|
||||
selectedRemoteRef.current = selectedRemote;
|
||||
}, [selectedRemote]);
|
||||
|
||||
// Generate description state
|
||||
const [isGeneratingDescription, setIsGeneratingDescription] = useState(false);
|
||||
@@ -110,10 +116,16 @@ export function CreatePRDialog({
|
||||
);
|
||||
setRemotes(remoteInfos);
|
||||
|
||||
// Auto-select 'origin' if available, otherwise first remote
|
||||
// Preserve existing selection if it's still valid; otherwise fall back to 'origin' or first remote
|
||||
if (remoteInfos.length > 0) {
|
||||
const defaultRemote = remoteInfos.find((r) => r.name === 'origin') || remoteInfos[0];
|
||||
setSelectedRemote(defaultRemote.name);
|
||||
const remoteNames = remoteInfos.map((r) => r.name);
|
||||
const currentSelection = selectedRemoteRef.current;
|
||||
const currentSelectionStillExists =
|
||||
currentSelection !== '' && remoteNames.includes(currentSelection);
|
||||
if (!currentSelectionStillExists) {
|
||||
const defaultRemote = remoteInfos.find((r) => r.name === 'origin') || remoteInfos[0];
|
||||
setSelectedRemote(defaultRemote.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -319,6 +319,7 @@ export function DiscardWorktreeChangesDialog({
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Failed to load diffs for discard dialog:', err);
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
} finally {
|
||||
setIsLoadingDiffs(false);
|
||||
}
|
||||
@@ -370,7 +371,7 @@ export function DiscardWorktreeChangesDialog({
|
||||
|
||||
if (result.success && result.result) {
|
||||
if (result.result.discarded) {
|
||||
const fileCount = filesToDiscard ? filesToDiscard.length : result.result.filesDiscarded;
|
||||
const fileCount = filesToDiscard ? filesToDiscard.length : selectedFiles.size;
|
||||
toast.success('Changes discarded', {
|
||||
description: `Discarded ${fileCount} ${fileCount === 1 ? 'file' : 'files'} in ${worktree.branch}`,
|
||||
});
|
||||
|
||||
@@ -167,10 +167,15 @@ export function MergeRebaseDialog({
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
const handleConfirm = async () => {
|
||||
if (!worktree || !selectedBranch) return;
|
||||
onConfirm(worktree, selectedBranch, selectedStrategy);
|
||||
onOpenChange(false);
|
||||
try {
|
||||
await onConfirm(worktree, selectedBranch, selectedStrategy);
|
||||
onOpenChange(false);
|
||||
} catch (err) {
|
||||
logger.error('Failed to confirm merge/rebase:', err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const selectedRemoteData = remotes.find((r) => r.name === selectedRemote);
|
||||
@@ -347,7 +352,11 @@ export function MergeRebaseDialog({
|
||||
className="bg-purple-600 hover:bg-purple-700 text-white"
|
||||
>
|
||||
<GitMerge className="w-4 h-4 mr-2" />
|
||||
Merge & Rebase
|
||||
{selectedStrategy === 'merge'
|
||||
? 'Merge'
|
||||
: selectedStrategy === 'rebase'
|
||||
? 'Rebase'
|
||||
: 'Merge & Rebase'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
@@ -69,6 +69,12 @@ export function SelectRemoteDialog({
|
||||
url: r.url,
|
||||
}));
|
||||
setRemotes(remoteInfos);
|
||||
setSelectedRemote((prev) => {
|
||||
if (prev && remoteInfos.some((r) => r.name === prev)) {
|
||||
return prev;
|
||||
}
|
||||
return remoteInfos.find((r) => r.name === 'origin')?.name ?? remoteInfos[0]?.name ?? '';
|
||||
});
|
||||
} else {
|
||||
setError(result.error || 'Failed to fetch remotes');
|
||||
}
|
||||
@@ -120,6 +126,12 @@ export function SelectRemoteDialog({
|
||||
url: r.url,
|
||||
}));
|
||||
setRemotes(remoteInfos);
|
||||
setSelectedRemote((prev) => {
|
||||
if (prev && remoteInfos.some((r) => r.name === prev)) {
|
||||
return prev;
|
||||
}
|
||||
return remoteInfos.find((r) => r.name === 'origin')?.name ?? remoteInfos[0]?.name ?? '';
|
||||
});
|
||||
} else {
|
||||
setError(result.error || 'Failed to refresh remotes');
|
||||
}
|
||||
|
||||
@@ -132,6 +132,9 @@ function parseDiff(diffText: string): ParsedFileDiff[] {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
// Skip trailing empty string produced by a final newline in diffText
|
||||
if (line === '' && i === lines.length - 1) continue;
|
||||
|
||||
if (line.startsWith('diff --git')) {
|
||||
if (currentFile) {
|
||||
if (currentHunk) currentFile.hunks.push(currentHunk);
|
||||
|
||||
@@ -47,7 +47,9 @@ interface ViewCommitsDialogProps {
|
||||
}
|
||||
|
||||
function formatRelativeDate(dateStr: string): string {
|
||||
if (!dateStr) return 'unknown date';
|
||||
const date = new Date(dateStr);
|
||||
if (isNaN(date.getTime())) return 'unknown date';
|
||||
const now = new Date();
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffSecs = Math.floor(diffMs / 1000);
|
||||
|
||||
Reference in New Issue
Block a user