Drop cookie import; click-through notifications; per-app zoom
The cookie import is gone. It worked mechanically - 43 cookies decrypted from Arc and verifiably visible to the page - but Google, Microsoft and Odoo all refused the imported sessions, because each binds a session to the browser that created it. Signing in once inside the app is simpler and actually works, so the whole path is deleted rather than kept as a feature that mostly fails. That takes rusqlite, aes, cbc, pbkdf2, hmac, sha1 and sha2 out of the build with it. Notifications are now raised through mac-notification-sys rather than Tauri's notification plugin, because the plugin cannot report that one was clicked. A click switches to the app that raised it and then runs the page's own click handler - the only thing that knows which message the notification was about. Zoom is per app, on a fixed ladder so Cmd+0 returns to exactly 100%. The shortcuts are menu-bar accelerators rather than a key listener, since the keystroke has to work while a remote page has focus. The hidden-element count is off the nav rows.
This commit is contained in:
+68
-25
@@ -43,6 +43,14 @@ pub struct UrlEvent {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
/// A notification the user clicked, and the page object that raised it.
|
||||
#[derive(Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NotificationClick {
|
||||
pub app_id: String,
|
||||
pub notification_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HiddenEvent {
|
||||
@@ -129,34 +137,11 @@ fn handle_sentinel(
|
||||
}
|
||||
|
||||
"notify" => {
|
||||
use tauri_plugin_notification::NotificationExt;
|
||||
let title = params.get("t").cloned().unwrap_or_default();
|
||||
let body = params.get("b").cloned().unwrap_or_default();
|
||||
let app_name = params.get("a").cloned().unwrap_or_default();
|
||||
// The app's own name leads, or a notification from four tools
|
||||
// in one window says nothing about which one wants you.
|
||||
let heading = if app_name.is_empty() {
|
||||
title.clone()
|
||||
} else {
|
||||
format!("{app_name} — {title}")
|
||||
};
|
||||
let outcome = match handle
|
||||
.notification()
|
||||
.builder()
|
||||
.title(heading.clone())
|
||||
.body(body)
|
||||
.show()
|
||||
{
|
||||
Ok(()) => "raised".to_string(),
|
||||
Err(e) => {
|
||||
eprintln!("could not raise a notification: {e}");
|
||||
format!("failed: {e}")
|
||||
}
|
||||
};
|
||||
// Recorded so the diagnostic can show that a page's notification
|
||||
// actually reached macOS, not merely that the shim ran.
|
||||
let state = handle.state::<crate::commands::AppState>();
|
||||
*state.last_notification.lock().unwrap() = format!("{heading} → {outcome}");
|
||||
let notification_id = params.get("id").cloned().unwrap_or_default();
|
||||
notify(&handle, &from, &app_name, &title, &body, notification_id);
|
||||
}
|
||||
|
||||
// Reports what the page found, over the same channel a real
|
||||
@@ -180,6 +165,58 @@ fn handle_sentinel(
|
||||
});
|
||||
}
|
||||
|
||||
/// Raises a macOS notification and waits, on its own thread, to see it clicked.
|
||||
///
|
||||
/// Not the notification plugin: that has no way to report a click, and a
|
||||
/// notification you cannot click through to the message is barely a
|
||||
/// notification. `send_notification` blocks until the user acts or it is
|
||||
/// dismissed, which is why this gets a thread of its own.
|
||||
fn notify(
|
||||
handle: &AppHandle,
|
||||
app_id: &str,
|
||||
app_name: &str,
|
||||
title: &str,
|
||||
body: &str,
|
||||
notification_id: String,
|
||||
) {
|
||||
// The app's own name leads, or a notification from four tools in one
|
||||
// window says nothing about which one wants you.
|
||||
let heading = if app_name.is_empty() { "Work".to_string() } else { app_name.to_string() };
|
||||
let subtitle = title.to_string();
|
||||
let message = body.to_string();
|
||||
let handle = handle.clone();
|
||||
let app_id = app_id.to_string();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let state = handle.state::<crate::commands::AppState>();
|
||||
let response = mac_notification_sys::send_notification(
|
||||
&heading,
|
||||
if subtitle.is_empty() { None } else { Some(&subtitle) },
|
||||
&message,
|
||||
None,
|
||||
);
|
||||
|
||||
match response {
|
||||
Ok(mac_notification_sys::NotificationResponse::Click) => {
|
||||
*state.last_notification.lock().unwrap() =
|
||||
format!("{heading} / {subtitle} → clicked");
|
||||
let _ = handle.emit(
|
||||
"notification-clicked",
|
||||
NotificationClick { app_id, notification_id },
|
||||
);
|
||||
}
|
||||
Ok(_) => {
|
||||
*state.last_notification.lock().unwrap() =
|
||||
format!("{heading} / {subtitle} → raised");
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("could not raise a notification: {e}");
|
||||
*state.last_notification.lock().unwrap() = format!("failed: {e}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Turns on WKWebView's two-finger back and forward swipes.
|
||||
///
|
||||
/// wry supports it but Tauri does not expose it, so it is set on the native
|
||||
@@ -280,6 +317,10 @@ pub fn create(
|
||||
|
||||
enable_swipe_navigation(handle, &id);
|
||||
|
||||
if let Some(wv) = handle.get_webview(&label_for(&id)) {
|
||||
let _ = wv.set_zoom(app.zoom);
|
||||
}
|
||||
|
||||
// Created hidden. `show_only` is what puts one on screen, so startup does
|
||||
// not flash every app in turn as they are built.
|
||||
if let Some(wv) = handle.get_webview(&label_for(&id)) {
|
||||
@@ -300,6 +341,7 @@ pub fn show_only(
|
||||
if Some(app.id.as_str()) == app_id {
|
||||
let _ = wv.set_position(LogicalPosition::new(stage.0, stage.1));
|
||||
let _ = wv.set_size(LogicalSize::new(stage.2, stage.3));
|
||||
let _ = wv.set_zoom(app.zoom);
|
||||
let _ = wv.show();
|
||||
} else {
|
||||
let _ = wv.hide();
|
||||
@@ -398,6 +440,7 @@ mod tests {
|
||||
group_id: None,
|
||||
user_agent: None,
|
||||
hidden: vec![".ad".into()],
|
||||
zoom: 1.0,
|
||||
order: 0,
|
||||
};
|
||||
let s = script_for(&app);
|
||||
|
||||
Reference in New Issue
Block a user