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