╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │41 else => 0, │ │42 }) }, │ │43 .user => switch (route) { │ │44 - .user, .user_settings, .user_auth => |name| .{ .user = try User.init(arena, haxy_moment, name) },│ │44 + .user => |u| .{ .user = try User.init(arena, haxy_moment, u.name, u.after) }, │ │45 + .user_settings, .user_auth => |name| .{ .user = try User.init(arena, haxy_moment, name, 0) }, │ │46 else => return error.UnexpectedRoute, │ │47 }, │ │48 .repo => switch (route) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │69 home_repos: usize, // 0 = first page │ │70 home_settings, │ │71 home_auth, │ │71 - user: Array(evt.User.name_max_len), │ │72 + user: struct { name: Array(evt.User.name_max_len), after: usize = 0 },│ │73 user_settings: Array(evt.User.name_max_len), │ │74 user_auth: Array(evt.User.name_max_len), │ │75 repo: Array(repo_route_max_len), │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │233 return switch (self) { │ │234 .home_users => |after| if (after == 0) @as([]const u8, "/users") else try std.fmt.allocPrint(arena.allocator(), "/users?after={d}", .{after}),│ │235 .home_repos => |after| if (after == 0) @as([]const u8, "/repos") else try std.fmt.allocPrint(arena.allocator(), "/repos?after={d}", .{after}),│ │235 - .user => |name| try std.fmt.allocPrint(arena.allocator(), user_segment ++ "{s}", .{name.slice()}), │ │236 + .user => |u| if (u.after == 0) │ │237 + try std.fmt.allocPrint(arena.allocator(), user_segment ++ "{s}", .{u.name.slice()}) │ │238 + else │ │239 + try std.fmt.allocPrint(arena.allocator(), user_segment ++ "{s}?after={d}", .{ u.name.slice(), u.after }), │ │240 .user_settings => |name| try std.fmt.allocPrint(arena.allocator(), user_segment ++ "{s}/settings", .{name.slice()}), │ │241 .user_auth => |name| try std.fmt.allocPrint(arena.allocator(), user_segment ++ "{s}/auth", .{name.slice()}), │ │242 .repo => |name| try std.fmt.allocPrint(arena.allocator(), repo_segment ++ "{s}", .{name.slice()}), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │283 if (std.mem.eql(u8, sub, "auth")) return .{ .user_auth = parsed };│ │284 return null; // unknown sub-path │ │285 } │ │282 - return .{ .user = parsed }; │ │286 + return .{ .user = .{ .name = parsed, .after = after } }; │ │287 } │ │288 // /repo/<username>/<reponame> (files root), then optionally /settings, │ │289 // /auth, or /files/<dir> for a directory in the files tab. the `repo` │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │366 return switch (a) { │ │367 .home_users => |a_after| a_after == b.home_users, │ │368 .home_repos => |a_after| a_after == b.home_repos, │ │365 - .user => |a_name| std.mem.eql(u8, a_name.slice(), b.user.slice()), │ │369 + .user => |a_u| std.mem.eql(u8, a_u.name.slice(), b.user.name.slice()) and a_u.after == b.user.after,│ │370 .user_settings => |a_name| std.mem.eql(u8, a_name.slice(), b.user_settings.slice()), │ │371 .user_auth => |a_name| std.mem.eql(u8, a_name.slice(), b.user_auth.slice()), │ │372 .repo => |a_name| std.mem.eql(u8, a_name.slice(), b.repo.slice()), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │388 return !a.eql(b); │ │389 } │ │390 │ │391 + // true when `a` and `b` are the same user paginated to a different repos │ │392 + // window. switching between a user's tabs is in-page (header-handled), so │ │393 + // only a changed `after` on the repos list navigates. │ │394 + pub fn userPageChanged(a: RoutablePage, b: RoutablePage) bool { │ │395 + return switch (a) { │ │396 + .user => |aa| switch (b) { │ │397 + .user => |bb| std.mem.eql(u8, aa.name.slice(), bb.name.slice()) and aa.after != bb.after,│ │398 + else => false, │ │399 + }, │ │400 + else => false, │ │401 + }; │ │402 + } │ │403 + │ │404 // true when `a` and `b` are the same home list tab paginated to a different │ │405 // window. switching between the users/repos tabs is in-page (the home page │ │406 // holds both lists), so only a changed `after` on the same tab navigates. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │427 try jw.objectField("kind"); │ │428 try jw.write(@tagName(self)); │ │429 switch (self) { │ │413 - .user, .user_settings, .user_auth => |name| {│ │430 + .user => |u| { │ │431 + try jw.objectField("name"); │ │432 + try jw.write(u.name.slice()); │ │433 + try jw.objectField("after"); │ │434 + try jw.write(u.after); │ │435 + }, │ │436 + .user_settings, .user_auth => |name| { │ │437 try jw.objectField("name"); │ │438 try jw.write(name.slice()); │ │439 }, │ ╰──────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │481 .home_repos => .{ .home_repos = helper.after }, │ │482 .home_settings => .home_settings, │ │483 .home_auth => .home_auth, │ │461 - .user => .{ .user = try parseName(evt.User.name_max_len, helper.name) }, │ │484 + .user => .{ .user = .{ .name = try parseName(evt.User.name_max_len, helper.name), .after = helper.after } },│ │485 .user_settings => .{ .user_settings = try parseName(evt.User.name_max_len, helper.name) }, │ │486 .user_auth => .{ .user_auth = try parseName(evt.User.name_max_len, helper.name) }, │ │487 .repo => .{ .repo = try parseName(repo_route_max_len, helper.name) }, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │819 // a link to a different parent page always navigates; within a page, a │ │820 // files-directory / commits-page / list-window change navigates while tab │ │821 // links stay in-page (header-handled). │ │799 - if (route.parent() != current.parent() or RoutablePage.repoPageChanged(route, current) or RoutablePage.homePageChanged(route, current)) return route; │ │822 + if (route.parent() != current.parent() or RoutablePage.repoPageChanged(route, current) or RoutablePage.homePageChanged(route, current) or RoutablePage.userPageChanged(route, current)) return route;│ │823 return null; │ │824 } │ │825 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯