1use crate::gui::{Message, State};
2use crate::theme;
3use iced::{
4 widget::{button, column, container, row, scrollable, text, text_input, Space},
5 Alignment, Element, Length,
6};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct AutoSwitchRule {
11 pub app_id: String,
12 pub profile_name: String,
13 pub device_id: Option<String>,
14 pub layer_id: Option<usize>,
15}
16
17#[derive(Debug, Clone, Default)]
18pub struct AutoSwitchRulesView {
19 pub device_id: String,
20 pub rules: Vec<AutoSwitchRule>,
21 pub editing_rule: Option<usize>,
22 pub new_app_id: String,
23 pub new_profile_name: String,
24 pub new_layer_id: String,
25}
26
27pub fn view(state: &State) -> Element<'_, Message> {
28 let view = state.auto_switch_view.as_ref().unwrap();
29
30 let focus_display = row![
31 text("Current Focus:").size(14),
32 Space::with_width(8),
33 if let Some(ref focus) = state.current_focus {
34 container(text(focus).size(14))
35 .padding([4, 12])
36 .style(theme::styles::card)
37 } else {
38 container(text("Unknown").size(14).style(iced::theme::Text::Color(
39 iced::Color::from_rgb(0.6, 0.6, 0.6),
40 )))
41 .padding([4, 12])
42 },
43 ]
44 .spacing(4)
45 .align_items(Alignment::Center);
46
47 let rules_header = row![
48 text("Auto-Switch Rules").size(18),
49 Space::with_width(Length::Fill),
50 if view.editing_rule.is_some() {
51 button("Cancel")
52 .on_press(Message::EditAutoSwitchRule(usize::MAX))
53 .style(iced::theme::Button::Text)
54 } else {
55 button("Add Rule")
56 .on_press(Message::EditAutoSwitchRule(usize::MAX))
57 .style(iced::theme::Button::Primary)
58 },
59 ]
60 .align_items(Alignment::Center);
61
62 let rules_list = if view.rules.is_empty() {
63 column![
64 Space::with_height(20),
65 text("No rules configured")
66 .size(14)
67 .style(iced::theme::Text::Color(iced::Color::from_rgb(
68 0.6, 0.6, 0.6
69 ))),
70 Space::with_height(8),
71 text("Add a rule to automatically switch profiles when windows gain focus")
72 .size(12)
73 .style(iced::theme::Text::Color(iced::Color::from_rgb(
74 0.5, 0.5, 0.5
75 ))),
76 ]
77 .align_items(Alignment::Center)
78 } else {
79 let mut list = column![].spacing(8);
80 for (idx, rule) in view.rules.iter().enumerate() {
81 let is_editing = view.editing_rule == Some(idx);
82 let indicator: Element<'_, Message> = if is_editing {
83 container(text("\u{25b6}")).padding([0, 8]).into()
84 } else {
85 Space::with_width(20).into()
86 };
87 let rule_row = row![
88 indicator,
89 column![
90 text(format!("App: {}", rule.app_id)).size(14),
91 text(format!(
92 "Profile: {}{}",
93 rule.profile_name,
94 rule.layer_id
95 .map(|l| format!(" + Layer {}", l))
96 .unwrap_or_default()
97 ))
98 .size(12),
99 ]
100 .spacing(2),
101 Space::with_width(Length::Fill),
102 button("Edit")
103 .on_press(Message::EditAutoSwitchRule(idx))
104 .style(iced::theme::Button::Text),
105 button("Delete")
106 .on_press(Message::DeleteAutoSwitchRule(idx))
107 .style(iced::theme::Button::Destructive),
108 ]
109 .spacing(8)
110 .align_items(Alignment::Center);
111 list = list.push(rule_row);
112 }
113 list
114 };
115
116 let edit_form = if view.editing_rule.is_some() {
117 Some(
118 column![
119 Space::with_height(20),
120 text(if view.editing_rule.unwrap_or(0) < view.rules.len() {
121 "Edit Rule"
122 } else {
123 "Add New Rule"
124 })
125 .size(16),
126 Space::with_height(12),
127 row![
128 text("App ID:").size(14),
129 Space::with_width(8),
130 text_input("org.alacritty", &view.new_app_id)
131 .on_input(Message::AutoSwitchAppIdChanged)
132 .padding(8)
133 .size(14),
134 Space::with_width(8),
135 button("Use Current")
136 .on_press(Message::AutoSwitchUseCurrentApp)
137 .style(iced::theme::Button::Secondary),
138 ]
139 .spacing(4)
140 .align_items(Alignment::Center),
141 Space::with_height(8),
142 row![
143 text("Profile:").size(14),
144 Space::with_width(8),
145 text_input("default", &view.new_profile_name)
146 .on_input(Message::AutoSwitchProfileNameChanged)
147 .padding(8)
148 .size(14),
149 ]
150 .spacing(4)
151 .align_items(Alignment::Center),
152 Space::with_height(8),
153 row![
154 text("Layer (optional):").size(14),
155 Space::with_width(8),
156 text_input("0", &view.new_layer_id)
157 .on_input(Message::AutoSwitchLayerIdChanged)
158 .padding(8)
159 .size(14),
160 ]
161 .spacing(4)
162 .align_items(Alignment::Center),
163 Space::with_height(12),
164 row![
165 Space::with_width(Length::Fill),
166 button("Save Rule")
167 .on_press(Message::SaveAutoSwitchRule)
168 .style(iced::theme::Button::Primary),
169 ]
170 .align_items(Alignment::Center),
171 ]
172 .spacing(4),
173 )
174 } else {
175 None
176 };
177
178 let mut content = column![
179 focus_display,
180 Space::with_height(20),
181 rules_header,
182 Space::with_height(12),
183 scrollable(rules_list).height(Length::Fixed(200.0)),
184 ]
185 .spacing(4);
186
187 if let Some(form) = edit_form {
188 content = content.push(form);
189 }
190
191 container(content)
192 .padding(20)
193 .width(Length::Fill)
194 .style(theme::styles::card)
195 .into()
196}