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)]
63 pub transport: Option<TransportKind>,
64 pub app_group: Option<String>,
66 pub extension_bundle_id: Option<String>,
68}
69
70impl WidgetsPluginConfig {
71 pub fn with_defaults(mut self, identifier: &str) -> Self {
74 let missing = self
75 .app_group
76 .as_deref()
77 .map(str::trim)
78 .unwrap_or("")
79 .is_empty();
80 if missing && !identifier.trim().is_empty() {
81 self.app_group = Some(format!("group.{}", identifier.trim()));
82 }
83 if let Some(group) = self.app_group.as_deref() {
84 crate::group::set_default_group(group);
85 }
86 self
87 }
88}
89
90pub fn env_transport_override() -> Option<TransportKind> {
92 std::env::var("WIDGET_TRANSPORT")
93 .ok()
94 .filter(|s| !s.is_empty())
95 .and_then(|s| TransportKind::parse(&s))
96}
97
98pub fn effective_transport(cfg: &WidgetsPluginConfig) -> TransportKind {
100 env_transport_override()
101 .or(cfg.transport)
102 .unwrap_or(if cfg!(target_os = "macos") {
103 TransportKind::WidgetContainer
104 } else {
105 TransportKind::AppGroup
106 })
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn parse_accepts_common_spellings() {
115 let cases = [
116 ("appGroup", TransportKind::AppGroup),
117 ("appgroup", TransportKind::AppGroup),
118 ("app_group", TransportKind::AppGroup),
119 ("app-group", TransportKind::AppGroup),
120 (" App-Group ", TransportKind::AppGroup),
121 ("userDefaults", TransportKind::UserDefaults),
122 ("user_defaults", TransportKind::UserDefaults),
123 ("user-defaults", TransportKind::UserDefaults),
124 ("defaults", TransportKind::UserDefaults),
125 ("widgetContainer", TransportKind::WidgetContainer),
126 ("widget_container", TransportKind::WidgetContainer),
127 ("widget-container", TransportKind::WidgetContainer),
128 ("container", TransportKind::WidgetContainer),
129 ("auto", TransportKind::Auto),
130 ("AUTO", TransportKind::Auto),
131 ];
132 for (raw, want) in cases {
133 assert_eq!(TransportKind::parse(raw), Some(want), "parse({raw:?})");
134 }
135 }
136
137 #[test]
138 fn parse_rejects_unknown() {
139 assert_eq!(TransportKind::parse(""), None);
140 assert_eq!(TransportKind::parse("app group"), None);
141 assert_eq!(TransportKind::parse("fanout"), None);
142 }
143
144 #[test]
145 fn as_str_roundtrips_through_parse() {
146 for kind in [
147 TransportKind::AppGroup,
148 TransportKind::UserDefaults,
149 TransportKind::WidgetContainer,
150 TransportKind::Auto,
151 ] {
152 assert_eq!(TransportKind::parse(kind.as_str()), Some(kind));
153 }
154 }
155
156 #[test]
157 fn env_overrides_conf() {
158 let cfg = WidgetsPluginConfig {
159 transport: Some(TransportKind::AppGroup),
160 ..Default::default()
161 };
162 let prev = std::env::var_os("WIDGET_TRANSPORT");
164 std::env::set_var("WIDGET_TRANSPORT", "widget-container");
165 assert_eq!(effective_transport(&cfg), TransportKind::WidgetContainer);
166 std::env::set_var("WIDGET_TRANSPORT", "");
167 assert_eq!(
168 effective_transport(&cfg),
169 TransportKind::AppGroup,
170 "empty env must not override"
171 );
172 match prev {
173 Some(v) => std::env::set_var("WIDGET_TRANSPORT", v),
174 None => std::env::remove_var("WIDGET_TRANSPORT"),
175 }
176 }
177}