diff --git a/src/main.rs b/src/main.rs index 00b86ae7..e9ea5f65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -299,6 +299,7 @@ async fn main() { app.at("/settings/restore").get(|r| settings::restore(r).boxed()); app.at("/settings/encoded-restore").post(|r| settings::encoded_restore(r).boxed()); app.at("/settings/update").get(|r| settings::update(r).boxed()); + app.at("/settings.json").get(|r| settings::get_json(r).boxed()); // RSS Subscriptions app.at("/r/:sub.rss").get(|r| subreddit::rss(r).boxed()); diff --git a/src/settings.rs b/src/settings.rs index bb9bb99e..137798f9 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -296,3 +296,28 @@ pub async fn encoded_restore(req: Request) -> Result, Strin Ok(redirect(&url)) } + +// Get current user settings as JSON for API consumption +pub async fn get_json(req: Request) -> Result, String> { + let prefs = Preferences::new(&req); + + // Try to encode preferences and return directly or error with HTTP status + match prefs.to_urlencoded() { + Ok(encoded) => { + Response::builder() + .status(200) + .header("content-type", "text/plain") + .header("cache-control", "no-cache, no-store, must-revalidate") + .body(encoded.into()) + .map_err(|e| format!("Failed to build response: {e}")) + } + Err(e) => { + eprintln!("Warning: Failed to encode preferences for settings transfer: {e}"); + Response::builder() + .status(500) + .header("content-type", "text/plain") + .body("Failed to encode preferences".into()) + .map_err(|e| format!("Failed to build error response: {e}")) + } + } +} diff --git a/static/check_update.js b/static/check_update.js index 3dcb406e..9cc2d8d6 100644 --- a/static/check_update.js +++ b/static/check_update.js @@ -39,15 +39,39 @@ async function checkInstanceUpdateStatus() { async function checkOtherInstances() { try { + // Fetch list of available instances const response = await fetch('/instances.json'); const data = await response.json(); const instances = window.location.host.endsWith('.onion') ? data.instances.filter(i => i.onion) : data.instances.filter(i => i.url); if (instances.length == 0) return; const randomInstance = instances[Math.floor(Math.random() * instances.length)]; const instanceUrl = randomInstance.url ?? randomInstance.onion; - // Set the href of the tag to the instance URL with path included - document.getElementById('random-instance').href = instanceUrl + window.location.pathname; - document.getElementById('random-instance').innerText = "Visit Random Instance"; + + // Fetch current user settings to transfer them to the new instance + let targetUrl = instanceUrl + window.location.pathname; + let text = "Visit Random Instance"; + + try { + const settingsResponse = await fetch('/settings.json'); + if (settingsResponse.ok) { + const urlEncoded = await settingsResponse.text(); + if (urlEncoded && urlEncoded.trim()) { + targetUrl = instanceUrl + '/settings/restore/?' + urlEncoded + '&redirect=' + encodeURIComponent(window.location.pathname.substring(1)); + text += " (bringing preferences)"; + } else { + console.warn('Settings encoding returned empty - visiting random instance without settings transfer'); + } + } else { + console.warn('Could not fetch user settings (HTTP', settingsResponse.status + ') - visiting random instance without settings transfer'); + } + } catch (settingsError) { + console.warn('Error fetching user settings:', settingsError); + console.warn('Visiting random instance without settings transfer'); + } + + // Set the href of the tag to the instance URL with path and settings included + document.getElementById('random-instance').href = targetUrl; + document.getElementById('random-instance').innerText = text; } catch (error) { console.error('Error fetching instances:', error); document.getElementById('update-status').innerText = '⚠️ Error checking other instances: ' + error;