╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │374 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .round_corners = true, .direction = .vert });│ │375 errdefer box.deinit(allocator); │ │376 │ │380 - // build the header first so we can grab the files-tab id for the auth │ │377 + // build the header first so we can grab the files-tab id for the user │ │378 // view (it focuses there after login). │ │379 { │ │380 var header_view = try Header.View.init(allocator, data, session); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │447 } │ │448 │ │449 // the header shows new repo with a login, and new user without one │ │453 - // and auth only outside local mode, so keep the stack's children │ │450 + // and user only outside local mode, so keep the stack's children │ │451 // 1:1 with the tabs by skipping the same views. │ │452 const identity = try std.fmt.allocPrint(session.page_arena.allocator(), "{s}/{s}", .{ data.header.owner_name, data.header.name });│ │453 if (session.data.user_id != null) { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │463 } │ │464 │ │465 if (session.data.host_kind == .server) { │ │469 - var auth_view = try Auth.View.init(allocator, &data.auth, session); │ │470 - errdefer auth_view.deinit(allocator); │ │471 - try stack.children.put(allocator, auth_view.getFocus().id, .{ .home_auth = auth_view });│ │466 + var user_view = try ui.UserLogout.initView(allocator, session); │ │467 + errdefer user_view.deinit(allocator); │ │468 + try stack.children.put(allocator, user_view.getFocus().id, user_view); │ │469 } │ │470 │ │471 if (session.is_terminal) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │21 const new_tab_label = "new"; │ │22 const new_repo_tab_bottom_label = "repo"; │ │23 const new_user_tab_bottom_label = "user"; │ │24 - │ │25 -pub const AuthTab = @import("./../AuthTab.zig"); │ │24 │ │25 const RefOrOid = ui.RoutablePage.RefOrOid; │ │26 const Array = ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len);│ ╰────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │138 │ │139 // every tab link is repo-scoped so selecting one stays on this page — │ │140 // switching its stack and updating the url — instead of navigating to │ │143 - // the global new repo or auth pages. the "ai:" prefix makes each an │ │141 + // the global new repo or user pages. the "ai:" prefix makes each an │ │142 // in-page anchor: crossPageLink ignores it so a wasm click just switches│ │143 // tabs (the page already holds every tab's content), while the href is │ │144 // still followed with js off. the files tab routes through the shared │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │169 const new_repo_link = try ui.inPageTabLink(session, new_repo_route, current_tag == .repo_new_repo); │ │170 const new_user_route = ui.RoutablePage{ .repo_new_user = Array.from(identity) orelse return error.RouteTooLong };│ │171 const new_user_link = try ui.inPageTabLink(session, new_user_route, current_tag == .repo_new_user); │ │174 - const auth_route = ui.RoutablePage{ .repo_auth = Array.from(identity) orelse return error.RouteTooLong }; │ │175 - const auth_link = try ui.inPageTabLink(session, auth_route, current_tag == .repo_auth); │ │172 + const user_route = ui.RoutablePage{ .repo_user = Array.from(identity) orelse return error.RouteTooLong }; │ │173 + const user_link = try ui.inPageTabLink(session, user_route, current_tag == .repo_user); │ │174 │ │175 // the tab matching the current page is focused initially; matching by │ │176 // link (rather than position) keeps this robust to tab changes. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │296 }); │ │297 } │ │298 │ │301 - // spacer pushes new repo, new user, and auth to the right│ │299 + // spacer pushes new repo, new user, and user to the right│ │300 { │ │301 var spacer = try ui.widget.Spacer.init(allocator); │ │302 errdefer spacer.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │335 }); │ │336 } │ │337 │ │340 - // auth tab (login / logout). AuthTab defaults to the global ai:/auth │ │341 - // link; repoint its instance at this repo's auth route so it stays on │ │342 - // this page. local mode has no accounts, so it has no auth tab. │ │338 + // user tab. local mode has no users, so it has none. │ │339 if (session.data.host_kind == .server) { │ │344 - var auth_tab = try AuthTab.View.init(allocator, session); │ │345 - errdefer auth_tab.deinit(allocator); │ │346 - auth_tab.text_box.getFocus().kind = .{ .custom = auth_link }; │ │347 - try tab_ids.put(allocator, auth_tab.getFocus().id, {}); │ │348 - if (current_tag == .repo_auth) selected_tab = auth_tab.getFocus().id; │ │349 - try tabs_box.children.put(allocator, auth_tab.getFocus().id, .{ │ │350 - .widget = .{ .auth_tab = auth_tab }, │ │340 + const label = ui.UserLogout.tabLabel(session); │ │341 + var text_box = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .round_corners = true, .wrap_kind = .none });│ │342 + errdefer text_box.deinit(allocator); │ │343 + text_box.getFocus().mode = .all; │ │344 + text_box.getFocus().kind = .{ .custom = user_link }; │ │345 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │346 + if (current_tag == .repo_user) selected_tab = text_box.getFocus().id; │ │347 + try tabs_box.children.put(allocator, text_box.getFocus().id, .{ │ │348 + .widget = .{ .text_box = text_box }, │ │349 .rect = null, │ │352 - .min_size = .{ .width = auth_tab.minWidth(), .height = null }, │ │350 + .min_size = .{ .width = label.len + 2, .height = null }, │ │351 }); │ │352 } │ │353 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │420 for (tabs_box.children.keys(), tabs_box.children.values()) |id, *child| { │ │421 const tb: ?*wgt.TextBox = switch (child.widget) { │ │422 .text_box => |*x| x, │ │425 - .auth_tab => |*at| blk: { │ │426 - // the label tracks login state per frame, so the width must too│ │427 - child.min_size = .{ .width = at.minWidth(), .height = null }; │ │428 - break :blk &at.text_box; │ │429 - }, │ │423 else => null, │ │424 }; │ │425 if (tb) |t| ui.widget.markSelected(t, selected_tab == id); │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/User.zig│ ╰───────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │14 const fork = @import("../fork.zig"); │ │15 │ │16 pub const Header = @import("./User/Header.zig"); │ │17 -pub const Auth = @import("./Auth.zig"); │ │17 pub const Quit = @import("./Quit.zig"); │ │18 │ │19 pub const page_size = 20; // how many repos one window of the repos tab shows│ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯