1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! The module provides the types for state management in Tauri.
//!
//! In Tauri, different states are distinguished by their unique types, thus we always
//! use structs to mark the states.

use crate::config::WidgetConfigCollection;
use std::{fs::create_dir_all, path::PathBuf, sync::Mutex};
use tauri::{menu::MenuItem, Runtime};

/// The type for the state of the collection of widget configurations.
///
/// The managed state will be updated at runtime and is thus protected by a mutex.
#[derive(Default)]
pub(crate) struct WidgetConfigCollectionState(pub(crate) Mutex<WidgetConfigCollection>);

/// The type for the state of the widget base directory.
///
/// This contains the path to the base directory `$APPDATA/widgets/` where all widgets
/// should be locally stored. This state is static and should not be changed during the
/// runtime.
pub(crate) struct WidgetBaseDirectoryState(pub(crate) PathBuf);

impl WidgetBaseDirectoryState {
    /// Initialize the widget base directory state.
    ///
    /// This creates the widget base directory if it does not exist.
    pub(crate) fn init(base: PathBuf) -> Self {
        let widget_base_dir = base.join("widgets");
        if !widget_base_dir.exists() {
            create_dir_all(&widget_base_dir).unwrap();
        }
        Self(widget_base_dir)
    }
}

/// Canvas click-through state information.
pub(crate) struct CanvasClickThrough<R: Runtime> {
    /// Whether the canvas is click-through.
    yes: bool,
    /// The menu item for toggling the canvas click-through state.
    menu_item: MenuItem<R>,
}

impl<R: Runtime> CanvasClickThrough<R> {
    /// Try to toggle the canvas click-through state.
    ///
    /// This is guaranteed to update whether the canvas is click-through or not. It may,
    /// however, fail to update the menu item text without an error beccause it is not
    /// worth panicking for such a minor thing.
    pub(crate) fn toggle(&mut self) {
        self.yes = !self.yes;
        let _ = self.menu_item.set_text(if self.yes { "Float" } else { "Sink" });
    }

    /// Get whether the canvas is click-through.
    pub(crate) fn yes(&self) -> bool {
        self.yes
    }
}

/// The type for the state of whether the canvas can be clicked through.
///
/// The managed state will be updated at runtime and is thus protected by a mutex.
pub(crate) struct CanvasClickThroughState<R: Runtime>(
    pub(crate) Mutex<CanvasClickThrough<R>>,
);

impl<R: Runtime> CanvasClickThroughState<R> {
    /// Initialize the canvas click-through state.
    pub(crate) fn init(is_click_through: bool, menu_item: MenuItem<R>) -> Self {
        Self(Mutex::new(CanvasClickThrough { yes: is_click_through, menu_item }))
    }
}