incular_platform/
system_environment.rs1use incular_config::{EdgeInsets, InputCapabilities, Locale, RuntimeEnvironment};
10use std::sync::{Arc, RwLock};
11
12#[derive(Clone, Debug, Default, PartialEq)]
14pub struct SystemEnvironmentPreferences {
15 pub locales: Option<Vec<Locale>>,
17 pub text_scale: Option<f32>,
20 pub reduced_motion: Option<bool>,
21 pub high_contrast: Option<bool>,
22 pub always_use_24_hour_format: Option<bool>,
23 pub accessible_navigation: Option<bool>,
24 pub invert_colors: Option<bool>,
25 pub on_off_switch_labels: Option<bool>,
26 pub bold_text: Option<bool>,
27 pub input: Option<InputCapabilities>,
28 pub safe_insets: Option<EdgeInsets>,
38 pub view_padding: Option<EdgeInsets>,
39 pub view_insets: Option<EdgeInsets>,
40}
41
42impl SystemEnvironmentPreferences {
43 pub fn apply_to(&self, environment: &mut RuntimeEnvironment) {
47 let defaults = RuntimeEnvironment::default();
48 environment.locales = self.locales.clone().unwrap_or(defaults.locales);
49 environment.text_scale = self.text_scale.unwrap_or(defaults.text_scale);
50 environment.reduced_motion = self.reduced_motion.unwrap_or(defaults.reduced_motion);
51 environment.high_contrast = self.high_contrast.unwrap_or(defaults.high_contrast);
52 environment.always_use_24_hour_format = self
53 .always_use_24_hour_format
54 .unwrap_or(defaults.always_use_24_hour_format);
55 environment.accessible_navigation = self
56 .accessible_navigation
57 .unwrap_or(defaults.accessible_navigation);
58 environment.invert_colors = self.invert_colors.unwrap_or(defaults.invert_colors);
59 environment.on_off_switch_labels = self
60 .on_off_switch_labels
61 .unwrap_or(defaults.on_off_switch_labels);
62 environment.bold_text = self.bold_text.unwrap_or(defaults.bold_text);
63 environment.input = self.input.unwrap_or(defaults.input);
64 environment.safe_insets = self.safe_insets.unwrap_or(defaults.safe_insets);
65 environment.view_padding = self.view_padding.unwrap_or(defaults.view_padding);
66 environment.view_insets = self.view_insets.unwrap_or(defaults.view_insets);
67 }
68}
69
70pub trait SystemEnvironmentProvider {
72 fn snapshot(&self) -> SystemEnvironmentPreferences;
73}
74
75#[derive(Clone, Default)]
77pub struct MemorySystemEnvironmentProvider {
78 snapshot: Arc<RwLock<SystemEnvironmentPreferences>>,
79}
80
81impl MemorySystemEnvironmentProvider {
82 #[must_use]
83 pub fn new(snapshot: SystemEnvironmentPreferences) -> Self {
84 Self {
85 snapshot: Arc::new(RwLock::new(snapshot)),
86 }
87 }
88
89 pub fn replace(&self, snapshot: SystemEnvironmentPreferences) -> bool {
92 let mut current = self.snapshot.write().expect("environment provider lock");
93 if *current == snapshot {
94 return false;
95 }
96 *current = snapshot;
97 true
98 }
99}
100
101impl SystemEnvironmentProvider for MemorySystemEnvironmentProvider {
102 fn snapshot(&self) -> SystemEnvironmentPreferences {
103 self.snapshot
104 .read()
105 .expect("environment provider lock")
106 .clone()
107 }
108}
109
110#[must_use]
113pub fn canonicalize_system_locales(
114 locales: impl IntoIterator<Item = impl AsRef<str>>,
115) -> Vec<Locale> {
116 let mut result = Vec::new();
117 for value in locales {
118 let Ok(locale) = value.as_ref().parse::<Locale>() else {
119 continue;
120 };
121 if !result.contains(&locale) {
122 result.push(locale);
123 }
124 }
125 result
126}