feat(app): tauri bridge commands for M2 (split/ratios/move/preset/restart/groups/meta)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 21:30:26 +07:00
parent 4b88d269e3
commit 0320a2f313
2 changed files with 60 additions and 0 deletions
+52
View File
@@ -7,6 +7,8 @@ use anyhow::{Context, Result};
use base64::Engine;
use serde_json::Value;
use spacesh_proto::codec::{read_frame, write_frame};
use spacesh_proto::message::{SplitDir, Edge, PresetSlot};
use spacesh_proto::ids::{GroupId, WorkspaceId};
use spacesh_proto::{Cmd, Envelope, Evt, SurfaceId};
use tauri::ipc::Channel;
use tauri::{AppHandle, Emitter};
@@ -193,3 +195,53 @@ pub async fn status(state: BridgeState<'_>) -> Result<Value, String> {
pub async fn close_surface(state: BridgeState<'_>, surface_id: String) -> Result<Value, String> {
data_of(state.request(Cmd::Close { surface_id: SurfaceId(surface_id) }).await.map_err(|e| e.to_string())?)
}
// ---- M2 commands ----
#[tauri::command]
pub async fn split_surface(state: BridgeState<'_>, surface_id: String, dir: String, command: Option<String>, args: Vec<String>) -> Result<Value, String> {
let dir = if dir == "down" { SplitDir::Down } else { SplitDir::Right };
data_of(state.request(Cmd::SplitSurface { surface_id: SurfaceId(surface_id), dir, command, args }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn set_ratios(state: BridgeState<'_>, workspace_id: String, node_path: Vec<u32>, ratios: Vec<f32>) -> Result<Value, String> {
data_of(state.request(Cmd::SetRatios { workspace_id: WorkspaceId(workspace_id), node_path, ratios }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn move_surface(state: BridgeState<'_>, surface_id: String, target_surface_id: String, edge: String) -> Result<Value, String> {
let edge = match edge.as_str() { "left" => Edge::Left, "top" => Edge::Top, "bottom" => Edge::Bottom, _ => Edge::Right };
data_of(state.request(Cmd::MoveSurface { surface_id: SurfaceId(surface_id), target_surface_id: SurfaceId(target_surface_id), edge }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn apply_preset(state: BridgeState<'_>, workspace_id: String, preset_id: String, slots: Vec<PresetSlot>) -> Result<Value, String> {
data_of(state.request(Cmd::ApplyPreset { workspace_id: WorkspaceId(workspace_id), preset_id, slots }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn restart_surface(state: BridgeState<'_>, surface_id: String) -> Result<Value, String> {
data_of(state.request(Cmd::RestartSurface { surface_id: SurfaceId(surface_id) }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn close_workspace(state: BridgeState<'_>, workspace_id: String) -> Result<Value, String> {
data_of(state.request(Cmd::CloseWorkspace { workspace_id: WorkspaceId(workspace_id) }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn set_workspace_meta(state: BridgeState<'_>, workspace_id: String, name: Option<String>, group_id: Option<String>, unread: Option<bool>, order: Option<u32>) -> Result<Value, String> {
// group_id: None from JS means "no change"; an explicit null is sent as Some("") to mean "ungroup".
let gid = match group_id {
None => None,
Some(s) if s.is_empty() => Some(None),
Some(s) => Some(Some(GroupId(s))),
};
data_of(state.request(Cmd::SetWorkspaceMeta { workspace_id: WorkspaceId(workspace_id), name, group_id: gid, unread, order }).await.map_err(|e| e.to_string())?)
}
#[tauri::command]
pub async fn create_group(state: BridgeState<'_>, name: String, color: String) -> Result<Value, String> {
data_of(state.request(Cmd::CreateGroup { name, color }).await.map_err(|e| e.to_string())?)
}
+8
View File
@@ -25,6 +25,14 @@ pub fn run() {
bridge::detach,
bridge::status,
bridge::close_surface,
bridge::split_surface,
bridge::set_ratios,
bridge::move_surface,
bridge::apply_preset,
bridge::restart_surface,
bridge::close_workspace,
bridge::set_workspace_meta,
bridge::create_group,
])
.run(tauri::generate_context!())
.expect("error while running spacesh");