diff --git a/app/src-tauri/src/bridge.rs b/app/src-tauri/src/bridge.rs index 1847d4d..82c484d 100644 --- a/app/src-tauri/src/bridge.rs +++ b/app/src-tauri/src/bridge.rs @@ -299,6 +299,17 @@ pub async fn focus(state: BridgeState<'_>, surface_id: String) -> Result, workspace_id: String, surface_id: Option) -> Result { + let cmd = Cmd::SetZoom { + workspace_id: spacesh_proto::WorkspaceId(workspace_id), + surface_id: surface_id.map(spacesh_proto::SurfaceId), + }; + data_of(state.request(cmd).await.map_err(|e| e.to_string())?) +} + // ---- M3 event log commands ---- #[tauri::command] diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index b632cf6..35a4bc9 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -49,6 +49,7 @@ pub fn run() { bridge::set_group, bridge::delete_group, bridge::focus, + bridge::set_zoom, bridge::event_log, bridge::mark_read, bridge::health, diff --git a/app/src/App.tsx b/app/src/App.tsx index 939adb9..9c2ece2 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -113,7 +113,7 @@ export function App() { )}
{active - ? + ? :
No workspace — create one to begin.
}
diff --git a/app/src/LayoutEngine.tsx b/app/src/LayoutEngine.tsx index b528116..e1c9e8b 100644 --- a/app/src/LayoutEngine.tsx +++ b/app/src/LayoutEngine.tsx @@ -1,10 +1,10 @@ import { useRef } from "react"; -import { Maximize2, RotateCw } from "lucide-react"; +import { Maximize2, Minimize2, RotateCw } from "lucide-react"; import { TerminalView } from "./TerminalView"; import { StatusRing } from "./StatusRing"; import { COLORS, FONT, STATE_COLOR } from "./theme"; import type { LayoutNode, SurfaceState, SurfaceView } from "./layoutTypes"; -import { setRatios, restartSurface } from "./socketBridge"; +import { setRatios, restartSurface, setZoom } from "./socketBridge"; interface Props { workspaceId: string; @@ -15,6 +15,7 @@ interface Props { surfaces: Record; focusedId: string | null; onFocus: (id: string) => void; + zoomed: string | null; } /** Collapse an absolute cwd into a ~/ style label for the panel header. */ @@ -23,21 +24,29 @@ function shortPath(cwd: string): string { return leaf ? `~/${leaf}` : cwd; } -export function LayoutEngine({ workspaceId, layout, running, states, surfaces, focusedId, onFocus }: Props) { +export function LayoutEngine({ workspaceId, layout, running, states, surfaces, focusedId, onFocus, zoomed }: Props) { if (!layout) { return
Empty workspace — apply a preset to add panels.
; } + if (zoomed) { + return ( +
+ +
+ ); + } return (
- +
); } -function Node({ workspaceId, node, path, running, states, surfaces, focusedId, onFocus }: { +function Node({ workspaceId, node, path, running, states, surfaces, focusedId, onFocus, zoomed }: { workspaceId: string; node: LayoutNode; path: number[]; running: Record; states: Record; surfaces: Record; focusedId: string | null; onFocus: (id: string) => void; + zoomed: string | null; }) { if ("leaf" in node) { const id = node.leaf.surface_id; @@ -60,10 +69,18 @@ function Node({ workspaceId, node, path, running, states, surfaces, focusedId, o return card(
Process exited
- +
+ + {zoomed === id && ( + + )} +
); } @@ -81,7 +98,11 @@ function Node({ workspaceId, node, path, running, states, surfaces, focusedId, o {state} - + {zoomed === id + ? { e.stopPropagation(); void setZoom(workspaceId, null); }} /> + : { e.stopPropagation(); onFocus(id); void setZoom(workspaceId, id); }} />}
@@ -102,7 +123,7 @@ function Node({ workspaceId, node, path, running, states, surfaces, focusedId, o next[i + 1] = Math.max(0.05, (next[i + 1] ?? 1) - deltaFrac); void setRatios(workspaceId, path, next); }}> - + ))}
diff --git a/app/src/layoutTypes.ts b/app/src/layoutTypes.ts index f725993..2730e1a 100644 --- a/app/src/layoutTypes.ts +++ b/app/src/layoutTypes.ts @@ -35,6 +35,7 @@ export interface WorkspaceView { order: number; unread: boolean; layout: LayoutNode | null; + zoomed: string | null; surfaces: Record; } diff --git a/app/src/socketBridge.ts b/app/src/socketBridge.ts index ab0afdf..8d102c1 100644 --- a/app/src/socketBridge.ts +++ b/app/src/socketBridge.ts @@ -181,3 +181,7 @@ export interface DaemonHealth { version: string; pid: number; started_at_ms: num export async function getHealth(): Promise { return await invoke("health"); } + +export async function setZoom(workspaceId: string, surfaceId: string | null): Promise { + await invoke("set_zoom", { workspaceId, surfaceId }); +}