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}