feat: persisted per-workspace panel zoom (proto + daemon, auto-clear on removal)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 12:16:44 +07:00
parent defceb1169
commit 2b1ccaf31d
5 changed files with 174 additions and 3 deletions
+17
View File
@@ -122,6 +122,11 @@ pub enum Cmd {
limit: Option<u32>,
},
MarkRead { target: MarkReadTarget },
SetZoom {
workspace_id: WorkspaceId,
#[serde(default, skip_serializing_if = "Option::is_none")]
surface_id: Option<SurfaceId>,
},
Health,
Status,
Shutdown,
@@ -322,6 +327,18 @@ mod tests {
assert_eq!(back, evt);
}
#[test]
fn set_zoom_cmd_round_trips() {
let z = Envelope::Req { id: 1, cmd: Cmd::SetZoom {
workspace_id: WorkspaceId("w_1".into()), surface_id: Some(SurfaceId("s_1".into())) } };
let j = serde_json::to_string(&z).unwrap();
assert!(j.contains(r#""cmd":"set_zoom""#));
assert_eq!(serde_json::from_str::<Envelope>(&j).unwrap(), z);
let unz = Envelope::Req { id: 2, cmd: Cmd::SetZoom {
workspace_id: WorkspaceId("w_1".into()), surface_id: None } };
assert_eq!(serde_json::from_str::<Envelope>(&serde_json::to_string(&unz).unwrap()).unwrap(), unz);
}
#[test]
fn health_cmd_round_trips() {
let env = Envelope::Req { id: 1, cmd: Cmd::Health };
+17
View File
@@ -42,6 +42,9 @@ pub struct Workspace {
/// None = empty workspace (no panels yet).
#[serde(default)]
pub layout: Option<LayoutNode>,
/// The single maximized surface for this workspace, if any.
#[serde(default)]
pub zoomed: Option<SurfaceId>,
pub surfaces: HashMap<SurfaceId, SurfaceSpec>,
}
@@ -66,6 +69,8 @@ pub struct WorkspaceView {
pub order: u32,
pub unread: bool,
pub layout: Option<LayoutNode>,
#[serde(default)]
pub zoomed: Option<SurfaceId>,
pub surfaces: HashMap<SurfaceId, SurfaceView>,
}
@@ -99,10 +104,22 @@ mod tests {
order: 0,
unread: false,
layout: None,
zoomed: None,
surfaces: HashMap::new(),
};
let j = serde_json::to_string(&w).unwrap();
let back: Workspace = serde_json::from_str(&j).unwrap();
assert_eq!(back, w);
}
#[test]
fn workspace_round_trips_with_zoom() {
let w = Workspace {
id: WorkspaceId("w_1".into()), path: "/tmp/p".into(), name: "p".into(),
group_id: None, order: 0, unread: false, layout: None,
zoomed: Some(SurfaceId("s_1".into())), surfaces: HashMap::new(),
};
let back: Workspace = serde_json::from_str(&serde_json::to_string(&w).unwrap()).unwrap();
assert_eq!(back, w);
}
}