Skip to main content

taskers_control/
protocol.rs

1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4use taskers_domain::{
5    AppModel, Direction, PaneId, PaneMetadataPatch, PersistedSession, SignalEvent, SplitAxis,
6    WindowFrame, WindowId, WorkspaceId, WorkspaceViewport, WorkspaceWindowId,
7};
8
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(tag = "command", rename_all = "snake_case")]
11pub enum ControlCommand {
12    CreateWorkspace {
13        label: String,
14    },
15    RenameWorkspace {
16        workspace_id: WorkspaceId,
17        label: String,
18    },
19    SwitchWorkspace {
20        window_id: Option<WindowId>,
21        workspace_id: WorkspaceId,
22    },
23    SplitPane {
24        workspace_id: WorkspaceId,
25        pane_id: Option<PaneId>,
26        axis: SplitAxis,
27    },
28    CreateWorkspaceWindow {
29        workspace_id: WorkspaceId,
30        direction: Direction,
31    },
32    FocusWorkspaceWindow {
33        workspace_id: WorkspaceId,
34        workspace_window_id: WorkspaceWindowId,
35    },
36    FocusPane {
37        workspace_id: WorkspaceId,
38        pane_id: PaneId,
39    },
40    FocusPaneDirection {
41        workspace_id: WorkspaceId,
42        direction: Direction,
43    },
44    ResizeActiveWindow {
45        workspace_id: WorkspaceId,
46        direction: Direction,
47        amount: i32,
48    },
49    ResizeActivePaneSplit {
50        workspace_id: WorkspaceId,
51        direction: Direction,
52        amount: i32,
53    },
54    SetWorkspaceWindowFrame {
55        workspace_id: WorkspaceId,
56        workspace_window_id: WorkspaceWindowId,
57        frame: WindowFrame,
58    },
59    SetWindowSplitRatio {
60        workspace_id: WorkspaceId,
61        workspace_window_id: WorkspaceWindowId,
62        path: Vec<bool>,
63        ratio: u16,
64    },
65    UpdatePaneMetadata {
66        pane_id: PaneId,
67        patch: PaneMetadataPatch,
68    },
69    SetWorkspaceViewport {
70        workspace_id: WorkspaceId,
71        viewport: WorkspaceViewport,
72    },
73    ClosePane {
74        workspace_id: WorkspaceId,
75        pane_id: PaneId,
76    },
77    CloseWorkspace {
78        workspace_id: WorkspaceId,
79    },
80    EmitSignal {
81        workspace_id: WorkspaceId,
82        pane_id: PaneId,
83        event: SignalEvent,
84    },
85    QueryStatus {
86        query: ControlQuery,
87    },
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
91#[serde(tag = "scope", rename_all = "snake_case")]
92pub enum ControlQuery {
93    ActiveWindow,
94    Window { window_id: WindowId },
95    Workspace { workspace_id: WorkspaceId },
96    All,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
100#[serde(tag = "status", rename_all = "snake_case")]
101pub enum ControlResponse {
102    Ack {
103        message: String,
104    },
105    WorkspaceCreated {
106        workspace_id: WorkspaceId,
107    },
108    PaneSplit {
109        pane_id: PaneId,
110    },
111    WorkspaceWindowCreated {
112        pane_id: PaneId,
113    },
114    Status {
115        session: PersistedSession,
116    },
117    WorkspaceState {
118        workspace_id: WorkspaceId,
119        session: PersistedSession,
120    },
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct RequestFrame {
125    pub request_id: Uuid,
126    pub command: ControlCommand,
127}
128
129#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
130pub struct ResponseFrame {
131    pub request_id: Uuid,
132    pub response: Result<ControlResponse, String>,
133}
134
135impl RequestFrame {
136    pub fn new(command: ControlCommand) -> Self {
137        Self {
138            request_id: Uuid::now_v7(),
139            command,
140        }
141    }
142}
143
144impl From<AppModel> for ControlResponse {
145    fn from(model: AppModel) -> Self {
146        Self::Status {
147            session: model.snapshot(),
148        }
149    }
150}