1use std::collections::BTreeMap;
6
7use a7n_proto::{MachineId, ProtoError, limits, v1};
8
9pub const SYNCED_KEYS: &[&str] = &[
10 "input.speed",
11 "input.natural_scrolling",
12 "hotkeys.double_tap",
13 "hotkeys.trigger_mode",
14 "hotkeys.hold_ms",
15 "hotkeys.shake",
16 "hotkeys.home",
17 "hotkeys.lock",
18 "hotkeys.jump",
19 "feedback.style",
20 "feedback.depth",
21 "feedback.radius",
22 "feedback.speed",
23 "feedback.frequency",
24 "feedback.intensity",
25 "feedback.color",
26 "feedback.size",
27 "feedback.landing_style",
28];
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct Settings {
32 pub set_at: u64,
33 pub by: MachineId,
34 pub values: BTreeMap<String, String>,
35}
36
37impl TryFrom<&v1::SettingsSync> for Settings {
38 type Error = ProtoError;
39
40 fn try_from(wire: &v1::SettingsSync) -> Result<Self, Self::Error> {
41 if wire.set_at > limits::COUNTER_MAX {
42 return Err(ProtoError::CounterTooLarge);
43 }
44 Ok(Self {
45 set_at: wire.set_at,
46 by: MachineId::try_from(wire.by.as_slice())?,
47 values: wire
48 .values
49 .iter()
50 .filter(|(key, _)| SYNCED_KEYS.contains(&key.as_str()))
51 .map(|(key, value)| (key.clone(), value.clone()))
52 .collect(),
53 })
54 }
55}
56
57impl Settings {
58 #[must_use]
59 pub fn to_proto(&self) -> v1::SettingsSync {
60 v1::SettingsSync {
61 on: true,
62 set_at: self.set_at,
63 by: self.by.as_bytes().to_vec(),
64 values: self
65 .values
66 .iter()
67 .map(|(key, value)| (key.clone(), value.clone()))
68 .collect(),
69 }
70 }
71}
72
73#[must_use]
74pub fn newer(current: Option<&Settings>, incoming: &Settings) -> bool {
75 current.is_none_or(|current| (incoming.set_at, incoming.by) > (current.set_at, current.by))
77}
78
79#[cfg(test)]
80mod tests;