purple_ssh/app/
form_state.rs1use crate::app::FormBaseline;
2use crate::app::forms::HostForm;
3use crate::app::tag_state::BulkTagEditorState;
4
5pub struct FormState {
10 pub(in crate::app) host: HostForm,
11 pub(in crate::app) host_baseline: Option<FormBaseline>,
12 pub(in crate::app) bulk_tag_editor: BulkTagEditorState,
13 pub(in crate::app) bulk_tag_undo: Option<Vec<(String, Vec<String>)>>,
18 discard_pending: bool,
22}
23
24impl FormState {
25 pub fn request_discard_confirm(&mut self) {
28 self.discard_pending = true;
29 }
30
31 pub fn dismiss_discard_confirm(&mut self) {
34 self.discard_pending = false;
35 }
36
37 pub fn is_discard_pending(&self) -> bool {
40 self.discard_pending
41 }
42
43 pub fn host(&self) -> &HostForm {
44 &self.host
45 }
46
47 pub fn host_mut(&mut self) -> &mut HostForm {
48 &mut self.host
49 }
50
51 pub fn host_baseline(&self) -> Option<&FormBaseline> {
52 self.host_baseline.as_ref()
53 }
54
55 pub fn set_host_baseline(&mut self, baseline: Option<FormBaseline>) {
56 self.host_baseline = baseline;
57 }
58
59 pub fn host_form_is_dirty(&self) -> bool {
61 match &self.host_baseline {
62 Some(b) => {
63 self.host.alias != b.alias
64 || self.host.hostname != b.hostname
65 || self.host.user != b.user
66 || self.host.port != b.port
67 || self.host.identity_file != b.identity_file
68 || self.host.proxy_jump != b.proxy_jump
69 || self.host.askpass != b.askpass
70 || self.host.vault_ssh != b.vault_ssh
71 || self.host.vault_addr != b.vault_addr
72 || self.host.tags != b.tags
73 }
74 None => false,
75 }
76 }
77
78 pub fn take_host_baseline(&mut self) -> Option<FormBaseline> {
79 self.host_baseline.take()
80 }
81
82 pub fn bulk_tag_editor(&self) -> &BulkTagEditorState {
83 &self.bulk_tag_editor
84 }
85
86 pub fn bulk_tag_editor_mut(&mut self) -> &mut BulkTagEditorState {
87 &mut self.bulk_tag_editor
88 }
89
90 pub fn bulk_tag_undo(&self) -> Option<&Vec<(String, Vec<String>)>> {
91 self.bulk_tag_undo.as_ref()
92 }
93
94 pub fn set_bulk_tag_undo(&mut self, undo: Option<Vec<(String, Vec<String>)>>) {
95 self.bulk_tag_undo = undo;
96 }
97
98 pub fn take_bulk_tag_undo(&mut self) -> Option<Vec<(String, Vec<String>)>> {
99 self.bulk_tag_undo.take()
100 }
101}
102
103impl Default for FormState {
104 fn default() -> Self {
105 Self {
106 host: HostForm::new(),
107 host_baseline: None,
108 bulk_tag_editor: BulkTagEditorState::default(),
109 bulk_tag_undo: None,
110 discard_pending: false,
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn default_is_empty() {
121 let s = FormState::default();
122 assert!(!s.is_discard_pending());
123 assert!(s.bulk_tag_undo.is_none());
124 assert!(s.host_baseline.is_none());
125 assert!(s.bulk_tag_editor.rows.is_empty());
126 }
127
128 #[test]
129 fn discard_confirm_lifecycle() {
130 let mut s = FormState::default();
131 assert!(!s.is_discard_pending());
132 s.request_discard_confirm();
133 assert!(s.is_discard_pending());
134 s.dismiss_discard_confirm();
135 assert!(!s.is_discard_pending());
136 }
137}