feat(desktop): manual window dragging and agent tab pruning

This commit is contained in:
Mohamed Boudra
2026-03-21 14:40:30 +07:00
parent 5ae7a0c9c2
commit 0bc693f157
16 changed files with 471 additions and 62 deletions
@@ -238,7 +238,7 @@ function DraftAgentScreenContent({
const activateExplorerTabForCheckout = usePanelStore(
(state) => state.activateExplorerTabForCheckout
)
const { style: dragRegionStyle, ...dragHandlers } = useDesktopDragHandlers()
const dragHandlers = useDesktopDragHandlers()
const isExplorerOpen = isMobile ? mobileView === 'file-explorer' : desktopFileExplorerOpen
const draftIdRef = useRef(generateDraftId())
const draftAgentIdRef = useRef(generateDraftId())
@@ -973,7 +973,7 @@ function DraftAgentScreenContent({
const explorerServerId = draftExplorerCheckout?.serverId ?? null
const explorerIsGit = draftExplorerCheckout?.isGit ?? false
const mainContent = (
<View style={[styles.container, dragRegionStyle]} {...dragHandlers}>
<View style={styles.container} {...dragHandlers}>
<View style={styles.outerContainer}>
<View style={styles.agentPanel}>
<View
@@ -21,7 +21,7 @@ export function OpenProjectScreen({ serverId }: { serverId: string }) {
const isMobile = UnistylesRuntime.breakpoint === "xs" || UnistylesRuntime.breakpoint === "sm";
const needsTrafficLightInset = !isMobile && !desktopAgentListOpen && getIsDesktopMac();
const trafficLightInset = needsTrafficLightInset ? trafficLightPadding.left : 0;
const { style: dragRegionStyle, ...dragHandlers } = useDesktopDragHandlers();
const dragHandlers = useDesktopDragHandlers();
useEffect(() => {
if (!isMobile) {
@@ -30,7 +30,7 @@ export function OpenProjectScreen({ serverId }: { serverId: string }) {
}, [isMobile, openAgentList]);
return (
<View style={[styles.container, dragRegionStyle]} {...dragHandlers}>
<View style={styles.container} {...dragHandlers}>
<View style={[styles.menuToggle, { paddingTop: insets.top, paddingLeft: trafficLightInset }]}>
<SidebarMenuToggle />
</View>
@@ -18,10 +18,10 @@ const styles = StyleSheet.create((theme) => ({
}));
export function StartupSplashScreen() {
const { style: dragRegionStyle, ...dragHandlers } = useDesktopDragHandlers();
const dragHandlers = useDesktopDragHandlers();
return (
<View style={[styles.container, dragRegionStyle]} {...dragHandlers}>
<View style={styles.container} {...dragHandlers}>
<PaseoLogo size={96} />
<Text style={styles.status}>Starting up…</Text>
</View>
@@ -101,14 +101,30 @@ describe("workspace agent visibility", () => {
).toBe(true);
});
it("does not prune archived agent tabs when knownAgentIds contains the agent", () => {
it("prunes archived agent tabs so archiving on one client closes tabs on all clients", () => {
const knownAgentIds = new Set(["archived-agent"]);
const activeAgentIds = new Set<string>();
expect(
shouldPruneWorkspaceAgentTab({
agentId: "archived-agent",
agentsHydrated: true,
knownAgentIds,
activeAgentIds,
})
).toBe(true);
});
it("does not prune active agent tabs", () => {
const knownAgentIds = new Set(["active-agent"]);
const activeAgentIds = new Set(["active-agent"]);
expect(
shouldPruneWorkspaceAgentTab({
agentId: "active-agent",
agentsHydrated: true,
knownAgentIds,
activeAgentIds,
})
).toBe(false);
});
@@ -119,6 +135,7 @@ describe("workspace agent visibility", () => {
agentId: "missing-agent",
agentsHydrated: true,
knownAgentIds: new Set<string>(),
activeAgentIds: new Set<string>(),
})
).toBe(true);
});
@@ -71,10 +71,15 @@ export function canOpenAgentTabFromRoute(input: {
return input.knownAgentIds.has(input.agentId);
}
// Prune agent tabs that are unknown (deleted) or archived.
// Archived agents get pruned so that archiving on one client closes the tab on all clients.
// Users can still explicitly open archived agents via navigation (openIntent),
// which re-creates the tab in a separate effect.
export function shouldPruneWorkspaceAgentTab(input: {
agentId: string;
agentsHydrated: boolean;
knownAgentIds: Set<string>;
activeAgentIds: Set<string>;
}): boolean {
if (!input.agentId.trim()) {
return false;
@@ -82,5 +87,5 @@ export function shouldPruneWorkspaceAgentTab(input: {
if (!input.agentsHydrated) {
return false;
}
return !input.knownAgentIds.has(input.agentId);
return !input.activeAgentIds.has(input.agentId);
}