Replace the website notification card with native desktop notification handling
Hop-State: A_06FPG6WWRGQW1NG5ZQZRSY0 Hop-Proposal: R_06FPG6WDJG2WNB21CHD30R0 Hop-Task: T_06FPG5CWT7W6DEF2HVENX20 Hop-Attempt: AT_06FPG5CWT7BEF2WDEP0BJQG
This commit is contained in:
+46
-3
@@ -1,11 +1,13 @@
|
||||
use reqwest::{Client, Method, StatusCode, Url};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::time::Duration;
|
||||
use tauri::webview::Cookie;
|
||||
use tauri::{State, WebviewWindow};
|
||||
use tauri::{Manager, State, WebviewWindow};
|
||||
|
||||
struct AppState {
|
||||
client: Client,
|
||||
notification_capability_sequence: AtomicU64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
@@ -251,13 +253,39 @@ async fn has_web_session(webview: WebviewWindow, node_url: String) -> Result<boo
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn open_web_app(webview: WebviewWindow, node_url: String) -> Result<(), String> {
|
||||
async fn open_web_app(
|
||||
state: State<'_, AppState>,
|
||||
webview: WebviewWindow,
|
||||
node_url: String,
|
||||
) -> Result<(), String> {
|
||||
let base = normalize_node(&node_url)?;
|
||||
let origin = base.origin().ascii_serialization();
|
||||
let capability_id = state
|
||||
.notification_capability_sequence
|
||||
.fetch_add(1, Ordering::Relaxed);
|
||||
let capability = remote_notification_capability(&origin, capability_id);
|
||||
webview
|
||||
.add_capability(capability)
|
||||
.map_err(|error| format!("Couldn’t enable native notifications for this node: {error}"))?;
|
||||
webview
|
||||
.navigate(base)
|
||||
.map_err(|error| format!("Couldn’t open the Synapsis web app: {error}"))
|
||||
}
|
||||
|
||||
fn remote_notification_capability(origin: &str, sequence: u64) -> String {
|
||||
serde_json::json!({
|
||||
"identifier": format!("synapsis-node-notifications-{sequence}"),
|
||||
"description": "Allow the active Synapsis node to send native desktop notifications",
|
||||
"local": false,
|
||||
"windows": ["main"],
|
||||
"remote": {
|
||||
"urls": [format!("{origin}/*")]
|
||||
},
|
||||
"permissions": ["notification:default"]
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn logout(state: State<'_, AppState>, node_url: String) -> Result<(), String> {
|
||||
let base = normalize_node(&node_url)?;
|
||||
@@ -285,7 +313,11 @@ pub fn run() {
|
||||
.expect("failed to build Synapsis HTTP client");
|
||||
|
||||
tauri::Builder::default()
|
||||
.manage(AppState { client })
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.manage(AppState {
|
||||
client,
|
||||
notification_capability_sequence: AtomicU64::new(0),
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
connect,
|
||||
login,
|
||||
@@ -346,4 +378,15 @@ mod tests {
|
||||
assert_eq!(cookies[0].http_only(), Some(true));
|
||||
assert_eq!(cookies[0].secure(), Some(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scopes_native_notifications_to_the_selected_node_origin() {
|
||||
let capability = remote_notification_capability("https://example.com", 7);
|
||||
let value: serde_json::Value = serde_json::from_str(&capability).unwrap();
|
||||
|
||||
assert_eq!(value["identifier"], "synapsis-node-notifications-7");
|
||||
assert_eq!(value["local"], false);
|
||||
assert_eq!(value["remote"]["urls"][0], "https://example.com/*");
|
||||
assert_eq!(value["permissions"][0], "notification:default");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user