Return to the native entry screen after the final website account logs out
Hop-State: A_06FPG94PH3WVGZM2V10TNC0 Hop-Proposal: R_06FPG943E08MTNDQMWHA0E8 Hop-Task: T_06FPG80D8VVAEPFXY3F8WGR Hop-Attempt: AT_06FPG80D8VE7RMJ24BEY3SR
This commit is contained in:
+80
-3
@@ -1,13 +1,15 @@
|
||||
use reqwest::{Client, Method, StatusCode, Url};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tauri::webview::Cookie;
|
||||
use tauri::webview::{Cookie, PageLoadEvent};
|
||||
use tauri::{Manager, State, WebviewWindow};
|
||||
|
||||
struct AppState {
|
||||
client: Client,
|
||||
notification_capability_sequence: AtomicU64,
|
||||
entry_url: Mutex<Option<Url>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
@@ -247,9 +249,17 @@ async fn has_web_session(webview: WebviewWindow, node_url: String) -> Result<boo
|
||||
let cookies = webview
|
||||
.cookies_for_url(base)
|
||||
.map_err(|error| format!("Couldn’t restore the web session: {error}"))?;
|
||||
Ok(cookies
|
||||
Ok(has_synapsis_session(&cookies))
|
||||
}
|
||||
|
||||
fn has_synapsis_session(cookies: &[Cookie<'_>]) -> bool {
|
||||
cookies
|
||||
.iter()
|
||||
.any(|cookie| cookie.name() == "synapsis_sessions" && !cookie.value().trim().is_empty()))
|
||||
.any(|cookie| cookie.name() == "synapsis_sessions" && !cookie.value().trim().is_empty())
|
||||
}
|
||||
|
||||
fn is_logged_out_explore(url: &Url, cookies: &[Cookie<'_>]) -> bool {
|
||||
url.path().trim_end_matches('/') == "/explore" && !has_synapsis_session(cookies)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -259,6 +269,19 @@ async fn open_web_app(
|
||||
node_url: String,
|
||||
) -> Result<(), String> {
|
||||
let base = normalize_node(&node_url)?;
|
||||
{
|
||||
let mut entry_url = state
|
||||
.entry_url
|
||||
.lock()
|
||||
.map_err(|_| "Couldn’t remember the app entry screen.".to_string())?;
|
||||
if entry_url.is_none() {
|
||||
*entry_url = Some(
|
||||
webview
|
||||
.url()
|
||||
.map_err(|error| format!("Couldn’t read the app entry address: {error}"))?,
|
||||
);
|
||||
}
|
||||
}
|
||||
let origin = base.origin().ascii_serialization();
|
||||
let capability_id = state
|
||||
.notification_capability_sequence
|
||||
@@ -317,6 +340,49 @@ pub fn run() {
|
||||
.manage(AppState {
|
||||
client,
|
||||
notification_capability_sequence: AtomicU64::new(0),
|
||||
entry_url: Mutex::new(None),
|
||||
})
|
||||
.on_page_load(|webview, payload| {
|
||||
if payload.event() != PageLoadEvent::Finished
|
||||
|| !matches!(payload.url().scheme(), "http" | "https")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let Ok(cookies) = webview.cookies_for_url(payload.url().clone()) else {
|
||||
return;
|
||||
};
|
||||
if !is_logged_out_explore(payload.url(), &cookies) {
|
||||
return;
|
||||
}
|
||||
|
||||
let state = webview.state::<AppState>();
|
||||
let mut entry_url = {
|
||||
let Ok(saved_entry_url) = state.entry_url.lock() else {
|
||||
return;
|
||||
};
|
||||
let Some(entry_url) = saved_entry_url.clone() else {
|
||||
return;
|
||||
};
|
||||
entry_url
|
||||
};
|
||||
|
||||
let client = state.client.clone();
|
||||
let node_url = payload.url().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Ok(base) = normalize_node(node_url.as_str()) {
|
||||
if let Ok(logout_url) = endpoint(&base, "/api/auth/logout") {
|
||||
let _ = client
|
||||
.post(logout_url)
|
||||
.json(&serde_json::json!({}))
|
||||
.send()
|
||||
.await;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
entry_url.set_query(Some("signedOut=1"));
|
||||
let _ = webview.navigate(entry_url);
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
connect,
|
||||
@@ -389,4 +455,15 @@ mod tests {
|
||||
assert_eq!(value["remote"]["urls"][0], "https://example.com/*");
|
||||
assert_eq!(value["permissions"][0], "notification:default");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_to_entry_only_for_logged_out_explore() {
|
||||
let explore = Url::parse("https://example.com/explore").unwrap();
|
||||
let timeline = Url::parse("https://example.com/").unwrap();
|
||||
let active_cookie = Cookie::new("synapsis_sessions", "active");
|
||||
|
||||
assert!(is_logged_out_explore(&explore, &[]));
|
||||
assert!(!is_logged_out_explore(&timeline, &[]));
|
||||
assert!(!is_logged_out_explore(&explore, &[active_cookie]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +245,15 @@ function App() {
|
||||
const [error, setError] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const launchParams = new URLSearchParams(window.location.search);
|
||||
if (launchParams.has("signedOut")) {
|
||||
localStorage.removeItem(SAVED_NODE_KEY);
|
||||
window.history.replaceState({}, "", window.location.pathname);
|
||||
setScreen("node");
|
||||
setBootstrapping(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const savedNode = localStorage.getItem(SAVED_NODE_KEY);
|
||||
if (!savedNode || !isTauri()) {
|
||||
setBootstrapping(false);
|
||||
|
||||
Reference in New Issue
Block a user