tauri_plugin_widgets/
config.rs1use serde::Deserialize;
4
5#[cfg(feature = "schema")]
6use schemars::JsonSchema;
7
8#[derive(Debug, Clone, Copy, Default, Deserialize, PartialEq, Eq)]
12#[cfg_attr(feature = "schema", derive(JsonSchema))]
13#[serde(rename_all = "camelCase")]
14pub enum TransportKind {
15 #[default]
18 AppGroup,
19 UserDefaults,
21 WidgetContainer,
23 Auto,
25}
26
27impl TransportKind {
28 pub fn parse(s: &str) -> Option<Self> {
30 match s.trim().to_ascii_lowercase().as_str() {
31 "appgroup" | "app_group" | "app-group" => Some(Self::AppGroup),
32 "userdefaults" | "user_defaults" | "user-defaults" | "defaults" => {
33 Some(Self::UserDefaults)
34 }
35 "widgetcontainer" | "widget_container" | "widget-container" | "container" => {
36 Some(Self::WidgetContainer)
37 }
38 "auto" => Some(Self::Auto),
39 _ => None,
40 }
41 }
42
43 pub fn as_str(self) -> &'static str {
45 match self {
46 Self::AppGroup => "appGroup",
47 Self::UserDefaults => "userDefaults",
48 Self::WidgetContainer => "widgetContainer",
49 Self::Auto => "auto",
50 }
51 }
52}
53
54#[derive(Debug, Clone, Deserialize, Default)]
56#[cfg_attr(feature = "schema", derive(JsonSchema))]
57#[serde(rename_all = "camelCase")]
58pub struct WidgetsPluginConfig {
59 #[serde(default)]
61 pub transport: TransportKind,
62 pub app_group: Option<String>,
64 pub extension_bundle_id: Option<String>,
66}
67
68pub fn env_transport_override() -> Option<TransportKind> {
70 std::env::var("WIDGET_TRANSPORT")
71 .ok()
72 .filter(|s| !s.is_empty())
73 .and_then(|s| TransportKind::parse(&s))
74}
75
76pub fn effective_transport(cfg: &WidgetsPluginConfig) -> TransportKind {
78 env_transport_override().unwrap_or(cfg.transport)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn parse_accepts_common_spellings() {
87 let cases = [
88 ("appGroup", TransportKind::AppGroup),
89 ("appgroup", TransportKind::AppGroup),
90 ("app_group", TransportKind::AppGroup),
91 ("app-group", TransportKind::AppGroup),
92 (" App-Group ", TransportKind::AppGroup),
93 ("userDefaults", TransportKind::UserDefaults),
94 ("user_defaults", TransportKind::UserDefaults),
95 ("user-defaults", TransportKind::UserDefaults),
96 ("defaults", TransportKind::UserDefaults),
97 ("widgetContainer", TransportKind::WidgetContainer),
98 ("widget_container", TransportKind::WidgetContainer),
99 ("widget-container", TransportKind::WidgetContainer),
100 ("container", TransportKind::WidgetContainer),
101 ("auto", TransportKind::Auto),
102 ("AUTO", TransportKind::Auto),
103 ];
104 for (raw, want) in cases {
105 assert_eq!(TransportKind::parse(raw), Some(want), "parse({raw:?})");
106 }
107 }
108
109 #[test]
110 fn parse_rejects_unknown() {
111 assert_eq!(TransportKind::parse(""), None);
112 assert_eq!(TransportKind::parse("app group"), None);
113 assert_eq!(TransportKind::parse("fanout"), None);
114 }
115
116 #[test]
117 fn as_str_roundtrips_through_parse() {
118 for kind in [
119 TransportKind::AppGroup,
120 TransportKind::UserDefaults,
121 TransportKind::WidgetContainer,
122 TransportKind::Auto,
123 ] {
124 assert_eq!(TransportKind::parse(kind.as_str()), Some(kind));
125 }
126 }
127
128 #[test]
129 fn env_overrides_conf() {
130 let cfg = WidgetsPluginConfig {
131 transport: TransportKind::AppGroup,
132 ..Default::default()
133 };
134 let prev = std::env::var_os("WIDGET_TRANSPORT");
136 std::env::set_var("WIDGET_TRANSPORT", "widget-container");
137 assert_eq!(effective_transport(&cfg), TransportKind::WidgetContainer);
138 std::env::set_var("WIDGET_TRANSPORT", "");
139 assert_eq!(
140 effective_transport(&cfg),
141 TransportKind::AppGroup,
142 "empty env must not override"
143 );
144 match prev {
145 Some(v) => std::env::set_var("WIDGET_TRANSPORT", v),
146 None => std::env::remove_var("WIDGET_TRANSPORT"),
147 }
148 }
149}