╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │2702 // widgets build). owned here, swapped on each navigation. session.page_arena│ │2703 // tracks whichever of these is current so widgets allocate into it. │ │2704 arena: *std.heap.ArenaAllocator, │ │2705 + // the login the current root was built for │ │2706 + user_id: ?[evt.event_id_size]u8, │ │2707 history: std.ArrayList(Entry), │ │2708 │ │2709 // each retained page keeps its own arena, freed when the page leaves the │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2710 // stack (popped on back, evicted at cap, or on deinit). this is what keeps a │ │2711 // long-lived session from accumulating every page it ever visited. │ │2710 - const Entry = struct { root: Widget, route: RoutablePage, arena: *std.heap.ArenaAllocator }; │ │2712 + const Entry = struct { root: Widget, route: RoutablePage, arena: *std.heap.ArenaAllocator, user_id: ?[evt.event_id_size]u8 };│ │2713 │ │2714 // cap on retained back-history so the chain can't grow memory without bound │ │2715 const max_history: usize = 16; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────╮ │2731 return .{ │ │2732 .root = try initRoot(allocator, page, session),│ │2733 .arena = arena, │ │2734 + .user_id = session.userId(), │ │2735 .history = .empty, │ │2736 }; │ │2737 } │ ╰─────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────╮ │2776 freeArena(allocator, self.arena);│ │2777 self.root = new_root; │ │2778 self.arena = arena; │ │2779 + self.user_id = session.userId(); │ │2780 } │ │2781 return; │ │2782 } │ ╰───────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │2788 freeArena(allocator, self.arena); │ │2789 self.root = entry.root; │ │2790 self.arena = entry.arena; │ │2791 + self.user_id = entry.user_id; │ │2792 session.page_arena = entry.arena; │ │2793 session.data.current_page = entry.route; │ │2794 + // a page built under another login is rebuilt rather than restored│ │2795 + if (!std.meta.eql(entry.user_id, session.userId())) { │ │2796 + session.refresh_requested = true; │ │2797 + return self.sync(allocator, session); │ │2798 + } │ │2799 chooseAnsiArtForNavigation(session); │ │2800 return; │ │2801 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2845 page.* = try Page.init(arena, session, route); │ │2846 const new_root = try initRoot(allocator, page, session); │ │2847 │ │2838 - try self.history.append(allocator, .{ .root = self.root, .route = previous_route, .arena = self.arena }); │ │2848 + try self.history.append(allocator, .{ .root = self.root, .route = previous_route, .arena = self.arena, .user_id = self.user_id });│ │2849 // drop the oldest entry (freeing its widget tree and arena) once over cap │ │2850 if (self.history.items.len > max_history) { │ │2851 var oldest = self.history.orderedRemove(0); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────╮ │2854 } │ │2855 self.root = new_root; │ │2856 self.arena = arena; │ │2857 + self.user_id = session.userId();│ │2858 } │ │2859 } │ │2860 }; │ ╰──────────────────────────────────────────────────╯