Skip to main content

tauri_plugin_widgets/
config.rs

1//! Plugin config from `tauri.conf.json` → `plugins.widgets`.
2
3use serde::Deserialize;
4
5/// Which Apple host→widget channel to use.
6///
7/// Pick this at build time (you know your signing). Do not rely on runtime fan-out.
8#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
9#[serde(rename_all = "camelCase")]
10pub enum TransportKind {
11    /// App Group shared container file (`widget_data.json`). Needs a real Team ID.
12    AppGroup,
13    /// App Group `UserDefaults` suite. Same signing requirements as [`AppGroup`].
14    UserDefaults,
15    /// Widget extension container file. Works with ad-hoc signing; macOS host must not be sandboxed.
16    WidgetContainer,
17    /// One-shot probe at startup (dev only). Prefer pinning an explicit driver in conf.
18    Auto,
19}
20
21impl Default for TransportKind {
22    fn default() -> Self {
23        // Production-safe default: shared App Group file. Use `auto` explicitly for ad-hoc probing.
24        Self::AppGroup
25    }
26}
27
28impl TransportKind {
29    /// Parse `WIDGET_TRANSPORT` / conf string.
30    pub fn parse(s: &str) -> Option<Self> {
31        match s.trim().to_ascii_lowercase().as_str() {
32            "appgroup" | "app_group" | "app-group" => Some(Self::AppGroup),
33            "userdefaults" | "user_defaults" | "user-defaults" | "defaults" => {
34                Some(Self::UserDefaults)
35            }
36            "widgetcontainer" | "widget_container" | "widget-container" | "container" => {
37                Some(Self::WidgetContainer)
38            }
39            "auto" => Some(Self::Auto),
40            _ => None,
41        }
42    }
43
44    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)]
55#[serde(rename_all = "camelCase")]
56pub struct WidgetsPluginConfig {
57    #[serde(default)]
58    pub transport: TransportKind,
59    /// App Group id, e.g. `group.com.example.app`.
60    pub app_group: Option<String>,
61    /// Widget extension bundle id (macOS container path). Default: `{app_id}.widgetkit`.
62    pub extension_bundle_id: Option<String>,
63}
64
65/// `WIDGET_TRANSPORT` overrides `plugins.widgets.transport` when set.
66pub fn env_transport_override() -> Option<TransportKind> {
67    std::env::var("WIDGET_TRANSPORT")
68        .ok()
69        .filter(|s| !s.is_empty())
70        .and_then(|s| TransportKind::parse(&s))
71}
72
73/// Merge conf + env into the effective kind.
74pub fn effective_transport(cfg: &WidgetsPluginConfig) -> TransportKind {
75    env_transport_override().unwrap_or(cfg.transport)
76}