datui_lib/app/
feedback.rs1#[derive(Default)]
5pub struct ErrorModal {
6 pub active: bool,
7 pub message: String,
8 pub scroll: usize,
10}
11
12impl ErrorModal {
13 pub fn new() -> Self {
14 Self::default()
15 }
16
17 pub fn show(&mut self, message: String) {
18 log::error!(target: "datui", "{message}");
21 self.active = true;
22 self.message = message;
23 self.scroll = 0;
24 }
25
26 pub fn hide(&mut self) {
27 self.active = false;
28 self.message.clear();
29 self.scroll = 0;
30 }
31}
32
33pub struct Flash {
39 pub message: String,
40 pub(crate) path_from: Option<usize>,
43 pub(crate) expires: std::time::Instant,
44}
45
46impl Flash {
47 pub(crate) fn new(message: String) -> Self {
48 Self {
49 message,
50 path_from: None,
51 expires: std::time::Instant::now() + std::time::Duration::from_secs(2),
52 }
53 }
54
55 pub(crate) fn path(prefix: &str, path: &std::path::Path) -> Self {
57 let mut flash = Self::new(format!("{prefix}{}", path.display()));
58 flash.path_from = Some(prefix.len());
59 flash
60 }
61
62 pub(crate) fn expired(&self) -> bool {
63 std::time::Instant::now() >= self.expires
64 }
65}
66
67pub(crate) enum Confirm {
70 ReadAll,
72 OpenLink(String),
73 ClearRecents,
74 QualityFullScan,
76 HideExamples,
77 DeleteView(String),
78 ForgetPlace(std::path::PathBuf),
79 QualityExport(
81 std::path::PathBuf,
82 crate::analysis::quality_export::ReportFormat,
83 ),
84 ChartExport(Box<crate::chart::chart_export::ChartExportRequest>),
85 Export(Box<crate::ExportRequest>),
86 Copy(crate::clipboard::CopyFormat, bool),
87 Download,
89 Reopen(Option<Box<crate::loading::open_options::KeptPlace>>),
92 Leave(crate::Leaving),
94}
95
96pub struct ConfirmationModal {
97 pub active: bool,
98 pub message: String,
99 pub focus_yes: bool, pub yes_label: &'static str,
102 pub no_label: &'static str,
104 pub scroll: usize,
106 pub(crate) asking: Option<Confirm>,
108}
109
110impl Default for ConfirmationModal {
111 fn default() -> Self {
112 Self {
113 active: false,
114 message: String::new(),
115 focus_yes: true,
116 yes_label: "Yes",
117 no_label: "No",
118 scroll: 0,
119 asking: None,
120 }
121 }
122}
123
124impl ConfirmationModal {
125 pub fn new() -> Self {
126 Self::default()
127 }
128
129 pub(crate) fn show(&mut self, message: String, asking: Confirm) {
130 self.active = true;
131 self.message = message;
132 self.focus_yes = true; self.yes_label = "Yes";
134 self.no_label = "No";
135 self.scroll = 0;
136 self.asking = Some(asking);
137 }
138
139 pub(crate) fn show_choice(
141 &mut self,
142 message: String,
143 yes_label: &'static str,
144 no_label: &'static str,
145 asking: Confirm,
146 ) {
147 self.show(message, asking);
148 self.yes_label = yes_label;
149 self.no_label = no_label;
150 }
151
152 pub(crate) fn show_destructive(
155 &mut self,
156 message: String,
157 yes_label: &'static str,
158 asking: Confirm,
159 ) {
160 self.show(message, asking);
161 self.focus_yes = false;
162 self.yes_label = yes_label;
163 }
164
165 pub(crate) fn take(&mut self) -> Option<Confirm> {
167 let asking = self.asking.take();
168 self.hide();
169 asking
170 }
171
172 pub fn asks_full_scan(&self) -> bool {
174 self.active && matches!(self.asking, Some(Confirm::QualityFullScan))
175 }
176
177 pub fn hide(&mut self) {
178 self.active = false;
179 self.message.clear();
180 self.focus_yes = true;
181 self.yes_label = "Yes";
182 self.no_label = "No";
183 self.scroll = 0;
184 self.asking = None;
185 }
186}