╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │302 } │ │303 } │ │304 │ │296 -fn handleLogout(request: *std.http.Server.Request, session_store: SessionStore) !void { │ │305 +fn handleLogout(request: *std.http.Server.Request, base: []const u8, session_store: SessionStore) !void {│ │306 // revoke the session server-side so the cookie is dead for anyone holding │ │307 // a copy, not just this browser. │ │308 if (getCookieValue(request, cookie_name)) |token| session_store.remove(token); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │309 + // return to the page the logout came from (base, or "/" at the root). │ │310 + const location: []const u8 = if (base.len == 0) "/" else base; │ │311 // close the connection instead of keeping it alive: we don't read the │ │312 // request body, and respond()'s keep-alive path would otherwise try to│ │313 // discard it — which asserts on a bodyless POST that carries no │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │317 .status = .see_other, │ │318 .keep_alive = false, │ │319 .extra_headers = &.{ │ │309 - .{ .name = "location", .value = ui.RoutablePage.url(.auth) }, │ │320 + .{ .name = "location", .value = location }, │ │321 .{ .name = "set-cookie", .value = cookie_name ++ "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" },│ │322 }, │ │323 }); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │327 io: std.Io, │ │328 request: *std.http.Server.Request,│ │329 allocator: std.mem.Allocator, │ │330 + base: []const u8, │ │331 admin_repo_path: []const u8, │ │332 session_store: SessionStore, │ │333 ) !void { │ ╰───────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │341 try evt.User.toggleAnsi(evt.admin_repo_opts, io, allocator, &repo, &user_id);│ │342 } │ │343 } │ │344 + │ │345 + // return to the settings tab the toggle came from so the change is visible. │ │346 + const location = try std.fmt.allocPrint(allocator, "{s}/settings", .{base}); │ │347 + defer allocator.free(location); │ │348 │ │349 // like logout, this is a bodyless POST, so close the connection rather than │ │350 // letting the keep-alive path try to discard a body that isn't framed. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │352 .status = .see_other, │ │353 .keep_alive = false, │ │354 .extra_headers = &.{ │ │339 - .{ .name = "location", .value = ui.RoutablePage.url(.settings) },│ │355 + .{ .name = "location", .value = location }, │ │356 }, │ │357 }); │ │358 } │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │375 var session = try ui.Session.init(&page_arena, &repo, session_data); │ │376 │ │377 const snapshot: ui.Snapshot = .{ │ │362 - .page = .{ .home = try .init(session.arena, session.haxy_moment orelse unreachable) }, │ │378 + .page = try ui.Page.init(session.arena, session.haxy_moment orelse unreachable, session.data.current_page),│ │379 .session = session.data, │ │380 }; │ │381 var root = try ui.initRoot(allocator, &snapshot.page, &session); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯