fix: optimistic archiving/closing and tab UX improvements

- Archive agents optimistically on close with rollback on error
- Close tabs immediately instead of waiting for RPC response
- Kill terminals in background with cache invalidation on failure
- Bulk close fires RPC in background, closes all tabs upfront
- Move new-tab button out of scroll area, rename to "New agent tab"
- Support invalidateQueries option in applyArchivedAgentCloseResults
- Fix workspace descriptor id/projectId types (string not number)
This commit is contained in:
Mohamed Boudra
2026-04-06 08:32:10 +07:00
parent 6362d429c7
commit d3e5d6929d
8 changed files with 212 additions and 135 deletions
@@ -14,8 +14,8 @@ import {
ArrowRightToLine,
Columns2,
Copy,
Plus,
Rows2,
SquarePen,
SquareTerminal,
X,
} from "lucide-react-native";
@@ -473,42 +473,36 @@ export function WorkspaceDesktopTabsRow({
);
}}
/>
</ScrollView>
<View style={styles.tabsActions} onLayout={handleTabsActionsLayout}>
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger asChild>
<Pressable
testID="workspace-new-tab"
onPress={() => onCreateDraftTab({ paneId })}
accessibilityRole="button"
accessibilityLabel="New tab"
style={styles.inlineNewTabButton}
>
{({ hovered, pressed }) => (
<Plus
size={theme.iconSize.md}
color={
hovered || pressed ? theme.colors.foreground : theme.colors.foregroundMuted
}
/>
)}
</Pressable>
<TooltipTrigger
testID="workspace-new-agent-tab"
onPress={() => onCreateDraftTab({ paneId })}
accessibilityRole="button"
accessibilityLabel="New agent tab"
style={({ hovered, pressed }) => [
styles.newTabActionButton,
(hovered || pressed) && styles.newTabActionButtonHovered,
]}
>
<SquarePen size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</TooltipTrigger>
<TooltipContent side="bottom" align="center" offset={8}>
<View style={styles.newTabTooltipRow}>
<Text style={styles.newTabTooltipText}>New tab</Text>
<Text style={styles.newTabTooltipText}>New agent tab</Text>
{newTabKeys ? (
<Shortcut chord={newTabKeys} style={styles.newTabTooltipShortcut} />
) : null}
</View>
</TooltipContent>
</Tooltip>
</ScrollView>
<View style={styles.tabsActions} onLayout={handleTabsActionsLayout}>
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
<TooltipTrigger
testID="workspace-new-terminal"
onPress={() => onCreateTerminalTab({ paneId })}
accessibilityRole="button"
accessibilityLabel="New terminal"
accessibilityLabel="New terminal tab"
style={({ hovered, pressed }) => [
styles.newTabActionButton,
(hovered || pressed) && styles.newTabActionButtonHovered,
@@ -518,7 +512,7 @@ export function WorkspaceDesktopTabsRow({
</TooltipTrigger>
<TooltipContent side="bottom" align="center" offset={8}>
<View style={styles.newTabTooltipRow}>
<Text style={styles.newTabTooltipText}>New terminal</Text>
<Text style={styles.newTabTooltipText}>New terminal tab</Text>
{newTerminalKeys ? (
<Shortcut chord={newTerminalKeys} style={styles.newTabTooltipShortcut} />
) : null}
@@ -819,13 +813,6 @@ const styles = StyleSheet.create((theme) => ({
tabCloseButtonActive: {
backgroundColor: theme.colors.surface3,
},
inlineNewTabButton: {
paddingHorizontal: theme.spacing[3],
height: "100%",
alignItems: "center",
justifyContent: "center",
borderRadius: 0,
},
newTabActionButton: {
width: 22,
height: 22,