1use super::{SettingData, SettingIdentity, SettingKind, ToggleSettings, WidgetKind};
4use crate::fl;
5use crate::settings::Settings;
6use crate::view::{Bus, EntryId, EntryKind, Event, ToggleEvent};
7
8#[cfg(any(feature = "tracing", feature = "profiling"))]
9use super::InputSettingKind;
10#[cfg(any(feature = "tracing", feature = "profiling"))]
11use crate::view::ViewId;
12use std::str::FromStr;
13
14pub struct LoggingEnabled;
16
17impl SettingKind for LoggingEnabled {
18 fn identity(&self) -> SettingIdentity {
19 SettingIdentity::LoggingEnabled
20 }
21
22 fn label(&self, _settings: &Settings) -> String {
23 fl!("settings-telemetry-enable-logging")
24 }
25
26 fn fetch(&self, settings: &Settings) -> SettingData {
27 SettingData {
28 value: settings.logging.enabled.to_string(),
29 widget: WidgetKind::Toggle {
30 left_label: fl!("settings-general-toggle-on"),
31 right_label: fl!("settings-general-toggle-off"),
32 enabled: settings.logging.enabled,
33 tap_event: Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled)),
34 },
35 }
36 }
37
38 fn handle(
39 &self,
40 evt: &Event,
41 settings: &mut Settings,
42 _bus: &mut Bus,
43 ) -> (Option<String>, bool) {
44 if let Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled)) = evt {
45 settings.logging.enabled = !settings.logging.enabled;
46 return (Some(settings.logging.enabled.to_string()), true);
47 }
48 (None, false)
49 }
50}
51
52pub struct LogLevel;
54
55impl LogLevel {
56 fn level_to_i18n(level: &tracing::Level) -> String {
57 match *level {
58 tracing::Level::TRACE => fl!("settings-log-level-trace"),
59 tracing::Level::DEBUG => fl!("settings-log-level-debug"),
60 tracing::Level::INFO => fl!("settings-log-level-info"),
61 tracing::Level::WARN => fl!("settings-log-level-warn"),
62 tracing::Level::ERROR => fl!("settings-log-level-error"),
63 }
64 }
65}
66
67impl SettingKind for LogLevel {
68 fn identity(&self) -> SettingIdentity {
69 SettingIdentity::LogLevel
70 }
71
72 fn label(&self, _settings: &Settings) -> String {
73 fl!("settings-telemetry-log-level")
74 }
75
76 fn fetch(&self, settings: &Settings) -> SettingData {
77 let current = tracing::Level::from_str(settings.logging.level.as_str())
78 .unwrap_or(tracing::Level::INFO);
79
80 let entries = vec![
81 EntryKind::RadioButton(
82 Self::level_to_i18n(&tracing::Level::TRACE),
83 EntryId::SetLogLevel(tracing::Level::TRACE),
84 current == tracing::Level::TRACE,
85 ),
86 EntryKind::RadioButton(
87 Self::level_to_i18n(&tracing::Level::DEBUG),
88 EntryId::SetLogLevel(tracing::Level::DEBUG),
89 current == tracing::Level::DEBUG,
90 ),
91 EntryKind::RadioButton(
92 Self::level_to_i18n(&tracing::Level::INFO),
93 EntryId::SetLogLevel(tracing::Level::INFO),
94 current == tracing::Level::INFO,
95 ),
96 EntryKind::RadioButton(
97 Self::level_to_i18n(&tracing::Level::WARN),
98 EntryId::SetLogLevel(tracing::Level::WARN),
99 current == tracing::Level::WARN,
100 ),
101 EntryKind::RadioButton(
102 Self::level_to_i18n(&tracing::Level::ERROR),
103 EntryId::SetLogLevel(tracing::Level::ERROR),
104 current == tracing::Level::ERROR,
105 ),
106 ];
107
108 SettingData {
109 value: Self::level_to_i18n(¤t),
110 widget: WidgetKind::SubMenu(entries),
111 }
112 }
113
114 fn handle(
115 &self,
116 evt: &Event,
117 settings: &mut Settings,
118 _bus: &mut Bus,
119 ) -> (Option<String>, bool) {
120 if let Event::Select(EntryId::SetLogLevel(ref level)) = evt {
121 settings.logging.level = level.to_string();
122 return (Some(Self::level_to_i18n(level)), true);
123 }
124 (None, false)
125 }
126}
127
128#[cfg(feature = "tracing")]
130pub struct OtlpEndpoint;
131
132#[cfg(feature = "tracing")]
133impl SettingKind for OtlpEndpoint {
134 fn identity(&self) -> SettingIdentity {
135 SettingIdentity::OtlpEndpoint
136 }
137
138 fn label(&self, _settings: &Settings) -> String {
139 fl!("settings-telemetry-otlp-endpoint")
140 }
141
142 fn fetch(&self, settings: &Settings) -> SettingData {
143 let value = settings
144 .logging
145 .otlp_endpoint
146 .clone()
147 .unwrap_or_else(|| fl!("settings-general-not-set"));
148
149 SettingData {
150 value,
151 widget: WidgetKind::ActionLabel(Event::Select(EntryId::EditOtlpEndpoint)),
152 }
153 }
154
155 fn as_input_kind(&self) -> Option<&dyn InputSettingKind> {
156 Some(self)
157 }
158}
159
160#[cfg(feature = "tracing")]
161impl InputSettingKind for OtlpEndpoint {
162 fn submit_view_id(&self) -> ViewId {
163 ViewId::OtlpEndpointInput
164 }
165
166 fn open_entry_id(&self) -> EntryId {
167 EntryId::EditOtlpEndpoint
168 }
169
170 fn input_label(&self) -> String {
171 fl!("settings-telemetry-otlp-endpoint")
172 }
173
174 fn input_max_chars(&self) -> usize {
175 50
176 }
177
178 fn current_text(&self, settings: &Settings) -> String {
179 settings.logging.otlp_endpoint.clone().unwrap_or_default()
180 }
181
182 fn apply_text(&self, text: &str, settings: &mut Settings) -> String {
183 let trimmed = text.trim();
184 settings.logging.otlp_endpoint = if trimmed.is_empty() {
185 None
186 } else {
187 Some(trimmed.to_string())
188 };
189 settings
190 .logging
191 .otlp_endpoint
192 .clone()
193 .unwrap_or_else(|| fl!("settings-general-not-set"))
194 }
195}
196
197#[cfg(feature = "profiling")]
199pub struct PyroscopeEndpoint;
200
201#[cfg(feature = "profiling")]
202impl SettingKind for PyroscopeEndpoint {
203 fn identity(&self) -> SettingIdentity {
204 SettingIdentity::PyroscopeEndpoint
205 }
206
207 fn label(&self, _settings: &Settings) -> String {
208 fl!("settings-telemetry-pyroscope-endpoint")
209 }
210
211 fn fetch(&self, settings: &Settings) -> SettingData {
212 let value = settings
213 .logging
214 .pyroscope_endpoint
215 .clone()
216 .unwrap_or_else(|| fl!("settings-general-not-set"));
217
218 SettingData {
219 value,
220 widget: WidgetKind::ActionLabel(Event::Select(EntryId::EditPyroscopeEndpoint)),
221 }
222 }
223
224 fn as_input_kind(&self) -> Option<&dyn InputSettingKind> {
225 Some(self)
226 }
227}
228
229#[cfg(feature = "profiling")]
230impl InputSettingKind for PyroscopeEndpoint {
231 fn submit_view_id(&self) -> ViewId {
232 ViewId::PyroscopeEndpointInput
233 }
234
235 fn open_entry_id(&self) -> EntryId {
236 EntryId::EditPyroscopeEndpoint
237 }
238
239 fn input_label(&self) -> String {
240 fl!("settings-telemetry-pyroscope-endpoint")
241 }
242
243 fn input_max_chars(&self) -> usize {
244 50
245 }
246
247 fn current_text(&self, settings: &Settings) -> String {
248 settings
249 .logging
250 .pyroscope_endpoint
251 .clone()
252 .unwrap_or_default()
253 }
254
255 fn apply_text(&self, text: &str, settings: &mut Settings) -> String {
256 let trimmed = text.trim();
257 settings.logging.pyroscope_endpoint = if trimmed.is_empty() {
258 None
259 } else {
260 Some(trimmed.to_string())
261 };
262 settings
263 .logging
264 .pyroscope_endpoint
265 .clone()
266 .unwrap_or_else(|| fl!("settings-general-not-set"))
267 }
268}
269
270#[cfg(all(feature = "test", feature = "kobo"))]
272pub struct EnableKernLog;
273
274#[cfg(all(feature = "test", feature = "kobo"))]
275impl SettingKind for EnableKernLog {
276 fn identity(&self) -> SettingIdentity {
277 SettingIdentity::EnableKernLog
278 }
279
280 fn label(&self, _settings: &Settings) -> String {
281 fl!("settings-telemetry-enable-kernel-log")
282 }
283
284 fn fetch(&self, settings: &Settings) -> SettingData {
285 SettingData {
286 value: settings.logging.enable_kern_log.to_string(),
287 widget: WidgetKind::Toggle {
288 left_label: fl!("settings-general-toggle-on"),
289 right_label: fl!("settings-general-toggle-off"),
290 enabled: settings.logging.enable_kern_log,
291 tap_event: Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableKernLog)),
292 },
293 }
294 }
295
296 fn handle(
297 &self,
298 evt: &Event,
299 settings: &mut Settings,
300 _bus: &mut Bus,
301 ) -> (Option<String>, bool) {
302 if let Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableKernLog)) = evt {
303 settings.logging.enable_kern_log = !settings.logging.enable_kern_log;
304 return (Some(settings.logging.enable_kern_log.to_string()), true);
305 }
306 (None, false)
307 }
308}
309
310#[cfg(all(feature = "test", feature = "kobo"))]
312pub struct EnableDbusLog;
313
314#[cfg(all(feature = "test", feature = "kobo"))]
315impl SettingKind for EnableDbusLog {
316 fn identity(&self) -> SettingIdentity {
317 SettingIdentity::EnableDbusLog
318 }
319
320 fn label(&self, _settings: &Settings) -> String {
321 fl!("settings-telemetry-enable-dbus-log")
322 }
323
324 fn fetch(&self, settings: &Settings) -> SettingData {
325 SettingData {
326 value: settings.logging.enable_dbus_log.to_string(),
327 widget: WidgetKind::Toggle {
328 left_label: fl!("settings-general-toggle-on"),
329 right_label: fl!("settings-general-toggle-off"),
330 enabled: settings.logging.enable_dbus_log,
331 tap_event: Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableDbusLog)),
332 },
333 }
334 }
335
336 fn handle(
337 &self,
338 evt: &Event,
339 settings: &mut Settings,
340 _bus: &mut Bus,
341 ) -> (Option<String>, bool) {
342 if let Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableDbusLog)) = evt {
343 settings.logging.enable_dbus_log = !settings.logging.enable_dbus_log;
344 return (Some(settings.logging.enable_dbus_log.to_string()), true);
345 }
346 (None, false)
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353 use crate::settings::Settings;
354 use crate::view::settings_editor::kinds::ToggleSettings;
355 use crate::view::{Bus, EntryId, Event, ToggleEvent};
356 use std::collections::VecDeque;
357
358 mod logging_enabled {
359 use super::*;
360
361 #[test]
362 fn handle_toggle_disables_when_enabled() {
363 let setting = LoggingEnabled;
364 let mut settings = Settings::default();
365 settings.logging.enabled = true;
366 let mut bus: Bus = VecDeque::new();
367 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled));
368
369 let result = setting.handle(&event, &mut settings, &mut bus);
370
371 assert!(result.0.is_some());
372 assert!(!settings.logging.enabled);
373 }
374
375 #[test]
376 fn handle_toggle_enables_when_disabled() {
377 let setting = LoggingEnabled;
378 let mut settings = Settings::default();
379 settings.logging.enabled = false;
380 let mut bus: Bus = VecDeque::new();
381 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled));
382
383 let result = setting.handle(&event, &mut settings, &mut bus);
384
385 assert!(result.0.is_some());
386 assert!(settings.logging.enabled);
387 }
388
389 #[test]
390 fn handle_returns_none_for_wrong_event() {
391 let setting = LoggingEnabled;
392 let mut settings = Settings::default();
393 let mut bus: Bus = VecDeque::new();
394
395 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
396
397 assert!(result.0.is_none());
398 }
399
400 #[test]
401 fn handle_returns_none_for_wrong_toggle() {
402 let setting = LoggingEnabled;
403 let mut settings = Settings::default();
404 let mut bus: Bus = VecDeque::new();
405
406 let result = setting.handle(
407 &Event::Toggle(ToggleEvent::Setting(ToggleSettings::SleepCover)),
408 &mut settings,
409 &mut bus,
410 );
411
412 assert!(result.0.is_none());
413 }
414 }
415
416 mod log_level {
417 use super::*;
418
419 #[test]
420 fn handle_set_level_updates_settings() {
421 let setting = LogLevel;
422 let mut settings = Settings::default();
423 settings.logging.level = "INFO".to_string();
424 let mut bus: Bus = VecDeque::new();
425 let event = Event::Select(EntryId::SetLogLevel(tracing::Level::WARN));
426
427 let result = setting.handle(&event, &mut settings, &mut bus);
428
429 assert!(result.0.is_some());
430 assert_eq!(settings.logging.level, "WARN");
431 }
432
433 #[test]
434 fn handle_can_set_all_levels() {
435 let setting = LogLevel;
436 let mut settings = Settings::default();
437 let mut bus: Bus = VecDeque::new();
438
439 for level in [
440 tracing::Level::TRACE,
441 tracing::Level::DEBUG,
442 tracing::Level::INFO,
443 tracing::Level::WARN,
444 tracing::Level::ERROR,
445 ] {
446 let event = Event::Select(EntryId::SetLogLevel(level));
447 setting.handle(&event, &mut settings, &mut bus);
448 assert_eq!(settings.logging.level, level.to_string());
449 }
450 }
451
452 #[test]
453 fn handle_returns_none_for_wrong_event() {
454 let setting = LogLevel;
455 let mut settings = Settings::default();
456 let mut bus: Bus = VecDeque::new();
457
458 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
459
460 assert!(result.0.is_none());
461 }
462 }
463
464 #[cfg(feature = "tracing")]
465 mod otlp_endpoint {
466 use super::*;
467 use crate::view::settings_editor::kinds::InputSettingKind;
468
469 #[test]
470 fn apply_text_sets_endpoint() {
471 let setting = OtlpEndpoint;
472 let mut settings = Settings::default();
473
474 let display = setting.apply_text("http://otel:4317", &mut settings);
475
476 assert_eq!(display, "http://otel:4317");
477 assert_eq!(
478 settings.logging.otlp_endpoint,
479 Some("http://otel:4317".to_string())
480 );
481 }
482
483 #[test]
484 fn apply_text_trims_whitespace() {
485 let setting = OtlpEndpoint;
486 let mut settings = Settings::default();
487
488 let display = setting.apply_text(" http://otel:4317 ", &mut settings);
489
490 assert_eq!(display, "http://otel:4317");
491 assert_eq!(
492 settings.logging.otlp_endpoint,
493 Some("http://otel:4317".to_string())
494 );
495 }
496
497 #[test]
498 fn apply_text_empty_clears_endpoint() {
499 let setting = OtlpEndpoint;
500 let mut settings = Settings::default();
501 settings.logging.otlp_endpoint = Some("http://old:4317".to_string());
502
503 let display = setting.apply_text("", &mut settings);
504
505 assert_eq!(display, "Not set");
506 assert_eq!(settings.logging.otlp_endpoint, None);
507 }
508
509 #[test]
510 fn apply_text_whitespace_only_clears_endpoint() {
511 let setting = OtlpEndpoint;
512 let mut settings = Settings::default();
513 settings.logging.otlp_endpoint = Some("http://old:4317".to_string());
514
515 let display = setting.apply_text(" ", &mut settings);
516
517 assert_eq!(display, "Not set");
518 assert_eq!(settings.logging.otlp_endpoint, None);
519 }
520 }
521
522 #[cfg(feature = "test")]
523 mod enable_kern_log {
524 use super::*;
525
526 #[test]
527 fn handle_toggle_enables_when_disabled() {
528 let setting = EnableKernLog;
529 let mut settings = Settings::default();
530 settings.logging.enable_kern_log = false;
531 let mut bus: Bus = VecDeque::new();
532 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableKernLog));
533
534 let result = setting.handle(&event, &mut settings, &mut bus);
535
536 assert!(result.0.is_some());
537 assert!(settings.logging.enable_kern_log);
538 }
539
540 #[test]
541 fn handle_toggle_disables_when_enabled() {
542 let setting = EnableKernLog;
543 let mut settings = Settings::default();
544 settings.logging.enable_kern_log = true;
545 let mut bus: Bus = VecDeque::new();
546 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableKernLog));
547
548 let result = setting.handle(&event, &mut settings, &mut bus);
549
550 assert!(result.0.is_some());
551 assert!(!settings.logging.enable_kern_log);
552 }
553
554 #[test]
555 fn handle_returns_none_for_wrong_event() {
556 let setting = EnableKernLog;
557 let mut settings = Settings::default();
558 let mut bus: Bus = VecDeque::new();
559
560 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
561
562 assert!(result.0.is_none());
563 }
564
565 #[test]
566 fn handle_returns_none_for_wrong_toggle() {
567 let setting = EnableKernLog;
568 let mut settings = Settings::default();
569 let mut bus: Bus = VecDeque::new();
570
571 let result = setting.handle(
572 &Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled)),
573 &mut settings,
574 &mut bus,
575 );
576
577 assert!(result.0.is_none());
578 }
579 }
580
581 #[cfg(all(feature = "test", feature = "kobo"))]
582 mod enable_dbus_log {
583 use super::*;
584
585 #[test]
586 fn handle_toggle_enables_when_disabled() {
587 let setting = EnableDbusLog;
588 let mut settings = Settings::default();
589 settings.logging.enable_dbus_log = false;
590 let mut bus: Bus = VecDeque::new();
591 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableDbusLog));
592
593 let result = setting.handle(&event, &mut settings, &mut bus);
594
595 assert!(result.0.is_some());
596 assert!(settings.logging.enable_dbus_log);
597 }
598
599 #[test]
600 fn handle_toggle_disables_when_enabled() {
601 let setting = EnableDbusLog;
602 let mut settings = Settings::default();
603 settings.logging.enable_dbus_log = true;
604 let mut bus: Bus = VecDeque::new();
605 let event = Event::Toggle(ToggleEvent::Setting(ToggleSettings::EnableDbusLog));
606
607 let result = setting.handle(&event, &mut settings, &mut bus);
608
609 assert!(result.0.is_some());
610 assert!(!settings.logging.enable_dbus_log);
611 }
612
613 #[test]
614 fn handle_returns_none_for_wrong_event() {
615 let setting = EnableDbusLog;
616 let mut settings = Settings::default();
617 let mut bus: Bus = VecDeque::new();
618
619 let result = setting.handle(&Event::Select(EntryId::About), &mut settings, &mut bus);
620
621 assert!(result.0.is_none());
622 }
623
624 #[test]
625 fn handle_returns_none_for_wrong_toggle() {
626 let setting = EnableDbusLog;
627 let mut settings = Settings::default();
628 let mut bus: Bus = VecDeque::new();
629
630 let result = setting.handle(
631 &Event::Toggle(ToggleEvent::Setting(ToggleSettings::LoggingEnabled)),
632 &mut settings,
633 &mut bus,
634 );
635
636 assert!(result.0.is_none());
637 }
638 }
639}