╭ changed ────────╮ │src/main_wasm.zig│ ╰─────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │63 .max_size = .{ .width = max_width, .height = max_height }, │ │64 }, root_ptr.getFocus()); │ │65 │ │66 - // mirror the page Header settled on into the browser URL. these are │ │67 - // passive same-page changes, like moving down the commits list, so we │ │68 - // replace the URL in place rather than pushing a history entry. real │ │69 - // cross-page navigations go through _navigate. │ │66 + // push input-driven in-page route changes into the browser url without │ │67 + // adding history entries. real cross-page navigations go through _navigate. │ │68 const current_page = session.data.current_page; │ │69 const should_push = if (last_pushed_page_maybe) |lp| !lp.eql(current_page) else true;│ │70 if (should_push) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │125 40 => .arrow_down, │ │126 else => return, │ │127 }; │ │128 + const root_focus = root_ptr.getFocus(); │ │129 + const focused_before = root_focus.grandchild_id; │ │130 │ │131 if (key == .enter) { │ │132 - if (root_ptr.getFocus().grandchild_id) |gid| { │ │132 + if (root_focus.grandchild_id) |gid| { │ │133 // follow a cross-page link │ │134 - if (ui.crossPageLink(root_ptr.getFocus(), gid, session.data)) |route| {│ │134 + if (ui.crossPageLink(root_focus, gid, session.data)) |route| { │ │135 const url = try route.toUrl(&page_arena); │ │136 _navigate(url.ptr, @intCast(url.len)); │ │137 return; │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │138 } │ │139 // follow a link to bytes the server serves directly│ │140 - if (ui.rawLink(root_ptr.getFocus(), gid)) |url| { │ │140 + if (ui.rawLink(root_focus, gid)) |url| { │ │141 _navigate(url.ptr, @intCast(url.len)); │ │142 return; │ │143 } │ ╰─────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │144 } │ │145 } │ │146 │ │147 - try root_ptr.input(allocator, key, root_ptr.getFocus()); │ │147 + try root_ptr.input(allocator, key, root_focus); │ │148 + const focused_after = root_focus.grandchild_id; │ │149 + if (key != .enter and focused_before == focused_after) return; │ │150 + const focus_id = focused_after orelse return; │ │151 + if (ui.inPageLink(root_focus, focus_id, session.data)) |route| session.data.current_page = route;│ │152 } │ │153 │ │154 fn onMouseClick(focus_id: usize) !void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────╮ │164 _navigate(url.ptr, @intCast(url.len));│ │165 return; │ │166 } │ │163 - root_ptr.getFocus().setFocus(focus_id); │ │167 + try setFocus(focus_id); │ │168 } │ │169 │ │170 fn setFocus(focus_id: usize) !void { │ ╰───────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │171 const root_ptr = if (root) |*root_value| root_value else return error.NotStarted; │ │168 - root_ptr.getFocus().setFocus(focus_id); │ │172 + const root_focus = root_ptr.getFocus(); │ │173 + root_focus.setFocus(focus_id); │ │174 + if (ui.inPageLink(root_focus, focus_id, session.data)) |route| session.data.current_page = route;│ │175 } │ │176 │ │177 fn consoleLog(arg: []const u8) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯