Skip to content

feat: preserve user settings when visiting random instance #454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
25 changes: 25 additions & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,28 @@ pub async fn encoded_restore(req: Request<Body>) -> Result<Response<Body>, Strin

Ok(redirect(&url))
}

// Get current user settings as JSON for API consumption
pub async fn get_json(req: Request<Body>) -> Result<Response<Body>, 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}"))
}
}
}
30 changes: 27 additions & 3 deletions static/check_update.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a> 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";

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let text = "Visit Random Instance"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion! Implemented this approach - much cleaner than my original variable naming.

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 <a> 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;
Expand Down