1use iced::widget::text_editor;
2use iced::window;
3use quincy::config::ClientConfig;
4use std::fmt;
5use std::path::PathBuf;
6use std::sync::Arc;
7use std::time::Instant;
8use tokio::sync::Mutex;
9
10use super::error::GuiError;
11use crate::ipc::{ConnectionMetrics, IpcConnection};
12
13#[derive(Debug, Clone, Default)]
18pub enum ConfigState {
19 #[default]
21 Idle,
22 Connecting {
24 started_at: Instant,
26 instance: Option<QuincyInstance>,
29 },
30 Connected {
32 instance: QuincyInstance,
34 metrics: Option<ConnectionMetrics>,
36 },
37 Disconnecting,
39 Error {
41 error: GuiError,
43 },
44}
45
46impl ConfigState {
47 pub fn is_connected(&self) -> bool {
49 matches!(self, Self::Connected { .. })
50 }
51
52 pub fn is_transitioning(&self) -> bool {
54 matches!(self, Self::Connecting { .. } | Self::Disconnecting)
55 }
56
57 pub fn has_active_instance(&self) -> bool {
59 matches!(
60 self,
61 Self::Connecting { .. } | Self::Connected { .. } | Self::Disconnecting
62 )
63 }
64
65 pub fn instance(&self) -> Option<&QuincyInstance> {
67 match self {
68 Self::Connected { instance, .. } => Some(instance),
69 _ => None,
70 }
71 }
72
73 pub fn instance_mut(&mut self) -> Option<&mut QuincyInstance> {
75 match self {
76 Self::Connected { instance, .. } => Some(instance),
77 _ => None,
78 }
79 }
80
81 pub fn metrics(&self) -> Option<&ConnectionMetrics> {
83 match self {
84 Self::Connected { metrics, .. } => metrics.as_ref(),
85 _ => None,
86 }
87 }
88
89 pub fn error(&self) -> Option<&GuiError> {
91 match self {
92 Self::Error { error } => Some(error),
93 _ => None,
94 }
95 }
96}
97
98#[derive(Clone)]
103pub struct QuincyInstance {
104 pub name: String,
106 pub(crate) ipc_client: Option<Arc<Mutex<IpcConnection>>>,
108}
109
110impl fmt::Debug for QuincyInstance {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 f.debug_struct("QuincyInstance")
113 .field("name", &self.name)
114 .field("has_ipc", &self.ipc_client.is_some())
115 .finish()
116 }
117}
118
119impl QuincyInstance {
120 pub fn new(name: String, ipc_client: Option<Arc<Mutex<IpcConnection>>>) -> Self {
122 Self { name, ipc_client }
123 }
124
125 pub fn ipc_client(&self) -> Option<&Arc<Mutex<IpcConnection>>> {
127 self.ipc_client.as_ref()
128 }
129
130 pub fn take_ipc_client(&mut self) -> Option<Arc<Mutex<IpcConnection>>> {
132 self.ipc_client.take()
133 }
134}
135
136#[derive(Clone)]
138pub struct QuincyConfig {
139 pub name: String,
141 pub path: PathBuf,
143}
144
145pub struct ConfigEntry {
147 pub config: QuincyConfig,
149 pub state: ConfigState,
151 pub parsed: Option<ClientConfig>,
153 pub parse_error: Option<String>,
155}
156
157#[derive(Debug)]
159pub struct EditorState {
160 pub config_name: String,
162 pub content: text_editor::Content,
164}
165
166#[derive(Debug, Clone)]
168pub struct ConfirmationState {
169 pub title: String,
170 pub message: String,
171 pub confirm_action: ConfirmAction,
172}
173
174#[derive(Debug, Clone)]
175pub enum ConfirmAction {
176 DeleteConfig(String), DiscardEditorChanges,
178}
179
180#[derive(Debug, Clone)]
182pub enum ConfigMsg {
183 Selected(String),
184 NameChanged(String),
185 NameSaved,
186 Delete,
187 New,
188}
189
190#[derive(Debug, Clone)]
191pub enum ConfirmMsg {
192 Show(ConfirmationState),
193 Confirm,
194 Cancel,
195}
196
197#[derive(Debug, Clone)]
198pub enum EditorMsg {
199 Action(text_editor::Action),
201 Open,
203 Close,
205 Save,
207}
208
209#[derive(Debug, Clone)]
211pub enum InstanceMsg {
212 Connect,
214 Connected(String),
216 ConnectedInstance(QuincyInstance, Option<ConnectionMetrics>),
218 Disconnect,
220 CancelConnect,
222 Disconnected,
224 StatusUpdated(String, Option<ConnectionMetrics>),
226 DisconnectedWithError(String, GuiError),
228 ConnectFailed(String, GuiError),
230}
231
232#[derive(Debug, Clone)]
233pub enum SystemMsg {
234 WindowClosed(window::Id),
235 UpdateMetrics,
236 Noop,
237}
238
239#[derive(Debug, Clone)]
240pub enum Message {
241 Config(ConfigMsg),
242 Editor(EditorMsg),
243 Instance(InstanceMsg),
244 System(SystemMsg),
245 Confirm(ConfirmMsg),
246}