generated from nhcarrigan/template
feat: add notification sounds (#44)
### Explanation _No response_ ### Issue _No response_ ### Attestations - [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [ ] I have run the linter and resolved any errors. - [ ] My pull request uses an appropriate title, matching the conventional commit standards. - [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [ ] All new and existing tests pass locally with my changes. - [ ] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning _No response_ Reviewed-on: #44 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #44.
This commit is contained in:
Generated
+262
-13
@@ -429,6 +429,12 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.43"
|
||||
@@ -1173,6 +1179,16 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
@@ -1401,12 +1417,15 @@ dependencies = [
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-notification",
|
||||
"tauri-plugin-opener",
|
||||
"tauri-plugin-os",
|
||||
"tauri-plugin-shell",
|
||||
"tauri-plugin-store",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"uuid",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1909,6 +1928,18 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "mac-notification-sys"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65fd3f75411f4725061682ed91f131946e912859d0044d39c4ec0aac818d7621"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.14.1"
|
||||
@@ -2039,12 +2070,38 @@ version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodrop"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
|
||||
[[package]]
|
||||
name = "notify-rust"
|
||||
version = "4.11.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6442248665a5aa2514e794af3b39661a8e73033b1cc5e59899e1276117ee4400"
|
||||
dependencies = [
|
||||
"futures-lite",
|
||||
"log",
|
||||
"mac-notification-sys",
|
||||
"serde",
|
||||
"tauri-winrt-notification",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@@ -2169,6 +2226,16 @@ dependencies = [
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
@@ -2273,8 +2340,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
@@ -2328,6 +2414,22 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"serde",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.3"
|
||||
@@ -2575,7 +2677,7 @@ checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"indexmap 2.13.0",
|
||||
"quick-xml",
|
||||
"quick-xml 0.38.4",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
@@ -2705,6 +2807,15 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.38.4"
|
||||
@@ -2754,6 +2865,16 @@ dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
@@ -2774,6 +2895,16 @@ dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.9.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
@@ -2792,6 +2923,15 @@ dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
@@ -3479,6 +3619,15 @@ dependencies = [
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-locale"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.2.2"
|
||||
@@ -3526,7 +3675,7 @@ dependencies = [
|
||||
"tao-macros",
|
||||
"unicode-segmentation",
|
||||
"url",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"windows-version",
|
||||
"x11-dl",
|
||||
@@ -3597,7 +3746,7 @@ dependencies = [
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"window-vibrancy",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3720,6 +3869,25 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-notification"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc"
|
||||
dependencies = [
|
||||
"log",
|
||||
"notify-rust",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-opener"
|
||||
version = "2.5.3"
|
||||
@@ -3738,10 +3906,28 @@ dependencies = [
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.17",
|
||||
"url",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-os"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997"
|
||||
dependencies = [
|
||||
"gethostname",
|
||||
"log",
|
||||
"os_info",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serialize-to-javascript",
|
||||
"sys-locale",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-shell"
|
||||
version = "2.3.4"
|
||||
@@ -3801,7 +3987,7 @@ dependencies = [
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3827,7 +4013,7 @@ dependencies = [
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"wry",
|
||||
]
|
||||
|
||||
@@ -3880,6 +4066,18 @@ dependencies = [
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-winrt-notification"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9"
|
||||
dependencies = [
|
||||
"quick-xml 0.37.5",
|
||||
"thiserror 2.0.17",
|
||||
"windows 0.61.3",
|
||||
"windows-version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.24.0"
|
||||
@@ -4557,7 +4755,7 @@ checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a"
|
||||
dependencies = [
|
||||
"webview2-com-macros",
|
||||
"webview2-com-sys",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
@@ -4581,7 +4779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
|
||||
dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
@@ -4637,11 +4835,23 @@ version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-collections 0.2.0",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future",
|
||||
"windows-future 0.2.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics",
|
||||
"windows-numerics 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future 0.3.2",
|
||||
"windows-numerics 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4653,6 +4863,15 @@ dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
@@ -4687,7 +4906,18 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading",
|
||||
"windows-threading 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-threading 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4734,6 +4964,16 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
@@ -4863,6 +5103,15 @@ dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-version"
|
||||
version = "0.1.7"
|
||||
@@ -5089,7 +5338,7 @@ dependencies = [
|
||||
"webkit2gtk",
|
||||
"webkit2gtk-sys",
|
||||
"webview2-com",
|
||||
"windows",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"windows-version",
|
||||
"x11-dl",
|
||||
|
||||
@@ -23,5 +23,15 @@ tokio = { version = "1", features = ["full"] }
|
||||
parking_lot = "0.12"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
tauri-plugin-store = "2.4.2"
|
||||
tauri-plugin-notification = "2"
|
||||
tauri-plugin-os = "2"
|
||||
tempfile = "3"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.62", features = [
|
||||
"Data_Xml_Dom",
|
||||
"UI_Notifications",
|
||||
"Win32_System_Com",
|
||||
"Win32_Foundation",
|
||||
] }
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ pub struct HikariConfig {
|
||||
|
||||
#[serde(default)]
|
||||
pub greeting_custom_prompt: Option<String>,
|
||||
|
||||
#[serde(default = "default_notifications_enabled")]
|
||||
pub notifications_enabled: bool,
|
||||
|
||||
#[serde(default = "default_notification_volume")]
|
||||
pub notification_volume: f32,
|
||||
}
|
||||
|
||||
impl Default for HikariConfig {
|
||||
@@ -59,6 +65,8 @@ impl Default for HikariConfig {
|
||||
theme: Theme::default(),
|
||||
greeting_enabled: true,
|
||||
greeting_custom_prompt: None,
|
||||
notifications_enabled: true,
|
||||
notification_volume: 0.7,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,6 +75,14 @@ fn default_greeting_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_notifications_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_notification_volume() -> f32 {
|
||||
0.7
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Theme {
|
||||
@@ -103,6 +119,8 @@ mod tests {
|
||||
theme: Theme::Light,
|
||||
greeting_enabled: true,
|
||||
greeting_custom_prompt: Some("Hello!".to_string()),
|
||||
notifications_enabled: true,
|
||||
notification_volume: 0.7,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&config).unwrap();
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
mod commands;
|
||||
mod config;
|
||||
mod notifications;
|
||||
mod types;
|
||||
mod wsl_bridge;
|
||||
mod wsl_notifications;
|
||||
mod vbs_notification;
|
||||
mod windows_toast;
|
||||
|
||||
use commands::*;
|
||||
use notifications::*;
|
||||
use wsl_bridge::create_shared_bridge;
|
||||
use wsl_notifications::*;
|
||||
use vbs_notification::*;
|
||||
use windows_toast::*;
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
@@ -15,6 +23,8 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_store::Builder::new().build())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.manage(bridge)
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
start_claude,
|
||||
@@ -25,6 +35,12 @@ pub fn run() {
|
||||
select_wsl_directory,
|
||||
get_config,
|
||||
save_config,
|
||||
send_windows_notification,
|
||||
send_simple_notification,
|
||||
send_windows_toast,
|
||||
send_notify_send,
|
||||
send_wsl_notification,
|
||||
send_vbs_notification,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
use tauri::command;
|
||||
use std::process::Command;
|
||||
|
||||
#[command]
|
||||
pub async fn send_notify_send(title: String, body: String) -> Result<(), String> {
|
||||
// Use notify-send for Linux/WSL
|
||||
let output = Command::new("notify-send")
|
||||
.arg(&title)
|
||||
.arg(&body)
|
||||
.arg("--urgency=normal")
|
||||
.arg("--app-name=Hikari Desktop")
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to execute notify-send: {}. Make sure libnotify-bin is installed.", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let error = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("notify-send failed: {}", error));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn send_windows_notification(title: String, body: String) -> Result<(), String> {
|
||||
// Create PowerShell script for Windows Toast Notification
|
||||
let ps_script = format!(
|
||||
r#"
|
||||
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
|
||||
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] > $null
|
||||
|
||||
$APP_ID = 'Hikari Desktop'
|
||||
|
||||
$template = @"
|
||||
<toast>
|
||||
<visual>
|
||||
<binding template="ToastText02">
|
||||
<text id="1">{}</text>
|
||||
<text id="2">{}</text>
|
||||
</binding>
|
||||
</visual>
|
||||
<audio src="ms-winsoundevent:Notification.Default" />
|
||||
</toast>
|
||||
"@
|
||||
|
||||
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
|
||||
$xml.LoadXml($template)
|
||||
|
||||
$toast = New-Object Windows.UI.Notifications.ToastNotification $xml
|
||||
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($APP_ID).Show($toast)
|
||||
"#,
|
||||
title.replace("\"", "`\""),
|
||||
body.replace("\"", "`\"")
|
||||
);
|
||||
|
||||
// Try PowerShell Core first (pwsh), then fall back to Windows PowerShell
|
||||
let output = Command::new("pwsh.exe")
|
||||
.arg("-NoProfile")
|
||||
.arg("-WindowStyle")
|
||||
.arg("Hidden")
|
||||
.arg("-Command")
|
||||
.arg(&ps_script)
|
||||
.output()
|
||||
.or_else(|_| {
|
||||
Command::new("powershell.exe")
|
||||
.arg("-NoProfile")
|
||||
.arg("-WindowStyle")
|
||||
.arg("Hidden")
|
||||
.arg("-Command")
|
||||
.arg(&ps_script)
|
||||
.output()
|
||||
})
|
||||
.map_err(|e| format!("Failed to execute PowerShell: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let error = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("PowerShell script failed: {}", error));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Alternative: Use Windows built-in MSG command for simple notifications
|
||||
#[command]
|
||||
pub async fn send_simple_notification(title: String, body: String) -> Result<(), String> {
|
||||
let message = format!("{}\n\n{}", title, body);
|
||||
|
||||
Command::new("cmd.exe")
|
||||
.arg("/c")
|
||||
.arg("msg")
|
||||
.arg("*")
|
||||
.arg(&message)
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to send message: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
use std::process::Command;
|
||||
use std::io::Write;
|
||||
use tempfile::NamedTempFile;
|
||||
use tauri::command;
|
||||
|
||||
#[command]
|
||||
pub async fn send_vbs_notification(title: String, body: String) -> Result<(), String> {
|
||||
// Create a VBScript that shows a Windows notification
|
||||
let vbs_content = format!(
|
||||
r#"
|
||||
Set objShell = CreateObject("WScript.Shell")
|
||||
objShell.Popup "{}" & vbCrLf & vbCrLf & "{}", 5, "{}", 64
|
||||
"#,
|
||||
body.replace("\"", "\"\"").replace("\n", "\" & vbCrLf & \""),
|
||||
title.replace("\"", "\"\""),
|
||||
title.replace("\"", "\"\"")
|
||||
);
|
||||
|
||||
// Create a temporary VBS file
|
||||
let mut temp_file = NamedTempFile::new()
|
||||
.map_err(|e| format!("Failed to create temp file: {}", e))?;
|
||||
|
||||
temp_file
|
||||
.write_all(vbs_content.as_bytes())
|
||||
.map_err(|e| format!("Failed to write VBS content: {}", e))?;
|
||||
|
||||
let temp_path = temp_file.path().to_string_lossy().to_string();
|
||||
|
||||
// Convert WSL path to Windows path
|
||||
let windows_path = if temp_path.starts_with("/mnt/") {
|
||||
// Convert /mnt/c/... to C:\...
|
||||
let path_parts: Vec<&str> = temp_path.split('/').collect();
|
||||
if path_parts.len() > 2 {
|
||||
let drive_letter = path_parts[2].to_uppercase();
|
||||
let rest_of_path = path_parts[3..].join("\\");
|
||||
format!("{}:\\{}", drive_letter, rest_of_path)
|
||||
} else {
|
||||
temp_path.clone()
|
||||
}
|
||||
} else if temp_path.starts_with("/tmp/") {
|
||||
// WSL temp files might be in a different location
|
||||
// Try to use wslpath to convert
|
||||
let output = Command::new("wslpath")
|
||||
.arg("-w")
|
||||
.arg(&temp_path)
|
||||
.output();
|
||||
|
||||
if let Ok(result) = output {
|
||||
if result.status.success() {
|
||||
String::from_utf8_lossy(&result.stdout).trim().to_string()
|
||||
} else {
|
||||
temp_path.clone()
|
||||
}
|
||||
} else {
|
||||
temp_path.clone()
|
||||
}
|
||||
} else {
|
||||
temp_path.clone()
|
||||
};
|
||||
|
||||
// Execute the VBScript using wscript.exe
|
||||
let output = Command::new("/mnt/c/Windows/System32/wscript.exe")
|
||||
.arg("//NoLogo")
|
||||
.arg(&windows_path)
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to execute VBScript: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let error = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("VBScript execution failed: {}", error));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
use tauri::command;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use windows::{
|
||||
core::{HSTRING, Result as WindowsResult},
|
||||
Data::Xml::Dom::*,
|
||||
UI::Notifications::*,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[command]
|
||||
pub async fn send_windows_toast(title: String, body: String) -> Result<(), String> {
|
||||
show_toast_notification(&title, &body)
|
||||
.map_err(|e| format!("Failed to show toast notification: {}", e))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn show_toast_notification(title: &str, body: &str) -> WindowsResult<()> {
|
||||
// Create the XML for the toast notification
|
||||
let toast_xml = format!(
|
||||
r#"<toast>
|
||||
<visual>
|
||||
<binding template="ToastGeneric">
|
||||
<text>{}</text>
|
||||
<text>{}</text>
|
||||
</binding>
|
||||
</visual>
|
||||
<audio src="ms-winsoundevent:Notification.Default" />
|
||||
</toast>"#,
|
||||
escape_xml(title),
|
||||
escape_xml(body)
|
||||
);
|
||||
|
||||
let xml_doc = XmlDocument::new()?;
|
||||
xml_doc.LoadXml(&HSTRING::from(toast_xml))?;
|
||||
|
||||
// Create the toast notification
|
||||
let toast = ToastNotification::CreateToastNotification(&xml_doc)?;
|
||||
|
||||
// Create a toast notifier with an application ID
|
||||
let notifier = ToastNotificationManager::CreateToastNotifierWithId(&HSTRING::from("Hikari Desktop"))?;
|
||||
|
||||
// Show the notification
|
||||
notifier.Show(&toast)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn escape_xml(text: &str) -> String {
|
||||
text.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
.replace('"', """)
|
||||
.replace('\'', "'")
|
||||
}
|
||||
|
||||
// Stub for non-Windows platforms
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[command]
|
||||
pub async fn send_windows_toast(_title: String, _body: String) -> Result<(), String> {
|
||||
Err("Windows toast notifications are only available on Windows".to_string())
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
use std::process::Command;
|
||||
use tauri::command;
|
||||
|
||||
#[command]
|
||||
pub async fn send_wsl_notification(title: String, body: String) -> Result<(), String> {
|
||||
// Method 1: Try Windows 10/11 toast notification using PowerShell
|
||||
let toast_command = format!(
|
||||
r#"
|
||||
Add-Type -AssemblyName System.Runtime.WindowsRuntime
|
||||
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
|
||||
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
|
||||
|
||||
$APP_ID = 'Hikari Desktop'
|
||||
|
||||
$template = @"
|
||||
<toast>
|
||||
<visual>
|
||||
<binding template="ToastGeneric">
|
||||
<text>{0}</text>
|
||||
<text>{1}</text>
|
||||
</binding>
|
||||
</visual>
|
||||
</toast>
|
||||
"@
|
||||
|
||||
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
|
||||
$xml.LoadXml($template -f ('{0}' -replace "'", "''"), ('{1}' -replace "'", "''"))
|
||||
|
||||
$toast = New-Object Windows.UI.Notifications.ToastNotification $xml
|
||||
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($APP_ID)
|
||||
$notifier.Show($toast)
|
||||
"#,
|
||||
title.replace("'", "''").replace("\"", "\\\""),
|
||||
body.replace("'", "''").replace("\"", "\\\"")
|
||||
);
|
||||
|
||||
// Try PowerShell.exe through WSL
|
||||
let output = Command::new("/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")
|
||||
.arg("-NoProfile")
|
||||
.arg("-ExecutionPolicy")
|
||||
.arg("Bypass")
|
||||
.arg("-WindowStyle")
|
||||
.arg("Hidden")
|
||||
.arg("-Command")
|
||||
.arg(&toast_command)
|
||||
.output();
|
||||
|
||||
match output {
|
||||
Ok(result) => {
|
||||
if result.status.success() {
|
||||
println!("WSL notification sent successfully");
|
||||
return Ok(());
|
||||
} else {
|
||||
let stderr = String::from_utf8_lossy(&result.stderr);
|
||||
println!("PowerShell toast failed: {}", stderr);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Failed to run PowerShell: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip msg.exe as it creates alert boxes
|
||||
// Method 2 removed
|
||||
|
||||
// Method 3: Try wsl-notify-send if available
|
||||
let notify_result = Command::new("wsl-notify-send")
|
||||
.arg("--appId")
|
||||
.arg("HikariDesktop")
|
||||
.arg("--category")
|
||||
.arg(&title)
|
||||
.arg(&body)
|
||||
.output();
|
||||
|
||||
if let Ok(result) = notify_result {
|
||||
if result.status.success() {
|
||||
println!("Notification sent via wsl-notify-send");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// If all methods fail, return an error
|
||||
Err("All WSL notification methods failed".to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user