fix(session): handle worktree deletion without sessions
This commit is contained in:
@@ -28,6 +28,7 @@ import { cn, formatPathForDisplay } from '@/lib/utils';
|
|||||||
import type { Session } from '@opencode-ai/sdk';
|
import type { Session } from '@opencode-ai/sdk';
|
||||||
import type { WorktreeMetadata } from '@/types/worktree';
|
import type { WorktreeMetadata } from '@/types/worktree';
|
||||||
import {
|
import {
|
||||||
|
archiveWorktree,
|
||||||
createWorktree,
|
createWorktree,
|
||||||
getWorktreeStatus,
|
getWorktreeStatus,
|
||||||
listWorktrees as listGitWorktrees,
|
listWorktrees as listGitWorktrees,
|
||||||
@@ -591,13 +592,30 @@ export const SessionDialogs: React.FC = () => {
|
|||||||
setIsProcessingDelete(true);
|
setIsProcessingDelete(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const archiveWorktree = shouldArchiveWorktree;
|
const shouldArchive = shouldArchiveWorktree;
|
||||||
const removeRemoteBranch = archiveWorktree && deleteDialogShouldRemoveRemote;
|
const removeRemoteBranch = shouldArchive && deleteDialogShouldRemoveRemote;
|
||||||
|
|
||||||
|
if (deleteDialog.sessions.length === 0 && isWorktreeDelete && deleteDialog.worktree) {
|
||||||
|
const shouldRemoveRemote = deleteDialogShouldRemoveRemote && canRemoveRemoteBranches;
|
||||||
|
await archiveWorktree({
|
||||||
|
projectDirectory: projectDirectory,
|
||||||
|
path: deleteDialog.worktree.path,
|
||||||
|
branch: deleteDialog.worktree.branch,
|
||||||
|
force: true,
|
||||||
|
deleteRemote: shouldRemoveRemote,
|
||||||
|
});
|
||||||
|
const archiveNote = shouldRemoveRemote ? 'Worktree and remote branch removed.' : 'Worktree removed.';
|
||||||
|
toast.success('Worktree removed', {
|
||||||
|
description: renderToastDescription(archiveNote),
|
||||||
|
});
|
||||||
|
closeDeleteDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (deleteDialog.sessions.length === 1) {
|
if (deleteDialog.sessions.length === 1) {
|
||||||
const target = deleteDialog.sessions[0];
|
const target = deleteDialog.sessions[0];
|
||||||
const success = await deleteSession(target.id, {
|
const success = await deleteSession(target.id, {
|
||||||
archiveWorktree,
|
archiveWorktree: shouldArchive,
|
||||||
deleteRemoteBranch: removeRemoteBranch,
|
deleteRemoteBranch: removeRemoteBranch,
|
||||||
});
|
});
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -605,7 +623,7 @@ export const SessionDialogs: React.FC = () => {
|
|||||||
setIsProcessingDelete(false);
|
setIsProcessingDelete(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const archiveNote = archiveWorktree
|
const archiveNote = shouldArchive
|
||||||
? removeRemoteBranch
|
? removeRemoteBranch
|
||||||
? 'Worktree and remote branch removed.'
|
? 'Worktree and remote branch removed.'
|
||||||
: 'Attached worktree archived.'
|
: 'Attached worktree archived.'
|
||||||
@@ -616,12 +634,12 @@ export const SessionDialogs: React.FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
const ids = deleteDialog.sessions.map((session) => session.id);
|
const ids = deleteDialog.sessions.map((session) => session.id);
|
||||||
const { deletedIds, failedIds } = await deleteSessions(ids, {
|
const { deletedIds, failedIds } = await deleteSessions(ids, {
|
||||||
archiveWorktree,
|
archiveWorktree: shouldArchive,
|
||||||
deleteRemoteBranch: removeRemoteBranch,
|
deleteRemoteBranch: removeRemoteBranch,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (deletedIds.length > 0) {
|
if (deletedIds.length > 0) {
|
||||||
const archiveNote = archiveWorktree
|
const archiveNote = shouldArchive
|
||||||
? removeRemoteBranch
|
? removeRemoteBranch
|
||||||
? 'Archived worktrees and removed remote branches.'
|
? 'Archived worktrees and removed remote branches.'
|
||||||
: 'Attached worktrees archived.'
|
: 'Attached worktrees archived.'
|
||||||
@@ -653,7 +671,7 @@ export const SessionDialogs: React.FC = () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsProcessingDelete(false);
|
setIsProcessingDelete(false);
|
||||||
}
|
}
|
||||||
}, [deleteDialog, deleteDialogShouldRemoveRemote, deleteSession, deleteSessions, closeDeleteDialog, shouldArchiveWorktree]);
|
}, [deleteDialog, deleteDialogShouldRemoveRemote, deleteSession, deleteSessions, closeDeleteDialog, shouldArchiveWorktree, isWorktreeDelete, canRemoveRemoteBranches, projectDirectory]);
|
||||||
|
|
||||||
const worktreeManagerBody = (
|
const worktreeManagerBody = (
|
||||||
<div className="space-y-4 w-full min-w-0">
|
<div className="space-y-4 w-full min-w-0">
|
||||||
@@ -929,27 +947,31 @@ export const SessionDialogs: React.FC = () => {
|
|||||||
const targetWorktree = deleteDialog?.worktree ?? deleteDialogSummaries[0]?.metadata ?? null;
|
const targetWorktree = deleteDialog?.worktree ?? deleteDialogSummaries[0]?.metadata ?? null;
|
||||||
const deleteDialogDescription = deleteDialog
|
const deleteDialogDescription = deleteDialog
|
||||||
? deleteDialog.mode === 'worktree'
|
? deleteDialog.mode === 'worktree'
|
||||||
? `This removes the selected worktree and ${deleteDialog.sessions.length === 1 ? '1 linked session' : `${deleteDialog.sessions.length} linked sessions`}.`
|
? deleteDialog.sessions.length === 0
|
||||||
|
? 'This removes the selected worktree.'
|
||||||
|
: `This removes the selected worktree and ${deleteDialog.sessions.length === 1 ? '1 linked session' : `${deleteDialog.sessions.length} linked sessions`}.`
|
||||||
: `This action permanently removes ${deleteDialog.sessions.length === 1 ? '1 session' : `${deleteDialog.sessions.length} sessions`}${deleteDialog.dateLabel ? ` from ${deleteDialog.dateLabel}` : ''
|
: `This action permanently removes ${deleteDialog.sessions.length === 1 ? '1 session' : `${deleteDialog.sessions.length} sessions`}${deleteDialog.dateLabel ? ` from ${deleteDialog.dateLabel}` : ''
|
||||||
}.`
|
}.`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const deleteDialogBody = deleteDialog ? (
|
const deleteDialogBody = deleteDialog ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="space-y-1.5 rounded-xl border border-border/40 bg-sidebar/60 p-3">
|
{deleteDialog.sessions.length > 0 && (
|
||||||
<ul className="space-y-0.5">
|
<div className="space-y-1.5 rounded-xl border border-border/40 bg-sidebar/60 p-3">
|
||||||
{deleteDialog.sessions.slice(0, 3).map((session) => (
|
<ul className="space-y-0.5">
|
||||||
<li key={session.id} className="typography-micro text-muted-foreground/80">
|
{deleteDialog.sessions.slice(0, 3).map((session) => (
|
||||||
{session.title || 'Untitled Session'}
|
<li key={session.id} className="typography-micro text-muted-foreground/80">
|
||||||
</li>
|
{session.title || 'Untitled Session'}
|
||||||
))}
|
</li>
|
||||||
{deleteDialog.sessions.length > 3 && (
|
))}
|
||||||
<li className="typography-micro text-muted-foreground/70">
|
{deleteDialog.sessions.length > 3 && (
|
||||||
+{deleteDialog.sessions.length - 3} more
|
<li className="typography-micro text-muted-foreground/70">
|
||||||
</li>
|
+{deleteDialog.sessions.length - 3} more
|
||||||
)}
|
</li>
|
||||||
</ul>
|
)}
|
||||||
</div>
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{isWorktreeDelete ? (
|
{isWorktreeDelete ? (
|
||||||
<div className="space-y-2 rounded-xl border border-border/40 bg-sidebar/60 p-3">
|
<div className="space-y-2 rounded-xl border border-border/40 bg-sidebar/60 p-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user