╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1483 .repo_members => |*r| r.name.slice(), │ │1484 .repo_branches => |*b| b.name.slice(), │ │1485 .repo_user => |*u| u.name.slice(), │ │1471 - .repo_settings, .repo_repo_new, .repo_user_new => |*name| name.slice(), │ │1486 + .repo_settings, .repo_delete, .repo_repo_new, .repo_user_new => |*name| name.slice(),│ │1487 else => null, │ │1488 }; │ │1489 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────╮ │1494 .fork_diff => |*d| &d.fork, │ │1495 .fork_files => |*f| &f.fork, │ │1496 .fork_commits => |*f| &f.fork,│ │1497 + .fork_delete => |*f| f, │ │1498 .fork_repo_new => |*f| f, │ │1499 .fork_user_new => |*f| f, │ │1500 .fork_user => |*u| &u.fork, │ ╰────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1528 return switch (self) { │ │1529 .home_about, .home_users, .home_repo_new, .home_user_new, .home_user => .home, │ │1530 .user_repos, .user_forks, .user_repo_new, .user_user_new, .user_user => .user, │ │1515 - .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_branches, .repo_repo_new, .repo_user_new, .repo_user => .repo, │ │1516 - .fork_patch, .fork_diff, .fork_files, .fork_commits, .fork_repo_new, .fork_user_new, .fork_user => .fork, │ │1531 + .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_branches, .repo_delete, .repo_repo_new, .repo_user_new, .repo_user => .repo,│ │1532 + .fork_patch, .fork_diff, .fork_files, .fork_commits, .fork_delete, .fork_repo_new, .fork_user_new, .fork_user => .fork, │ │1533 .not_found => .not_found, │ │1534 }; │ │1535 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1551 } │ │1552 │ │1553 // the tail after a page's "user": none or "notifications" with an optional │ │1538 - // "start:<n>", "settings", "keys" with an optional "key:<fingerprint>" and │ │1554 + // "start:<n>", "settings", "delete", "keys" with an optional "key:<fingerprint>" and │ │1555 // removal confirmation, or "new" │ │1556 fn userTail(segments: *std.mem.SplitIterator(u8, .scalar)) ?union(enum) { new, tab: UserTab } {│ │1557 const word = segments.next() orelse return .{ .tab = .{} }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1558 if (std.mem.eql(u8, word, "new")) return if (segments.next() == null) .new else null; │ │1559 return switch (std.meta.stringToEnum(UserView, word) orelse return null) { │ │1560 .settings => if (segments.next() == null) .{ .tab = .{ .view = .settings } } else null,│ │1561 + .delete => if (segments.next() == null) .{ .tab = .{ .view = .delete } } else null, │ │1562 .keys => .{ .tab = keysTab(segments) orelse return null }, │ │1563 .notifications => .{ .tab = .{ .start = listStart(segments) orelse return null } }, │ │1564 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1635 var route = repoBranchesRoute(pair) orelse return null; │ │1636 if (params.values.get(.branch)) |branch| route.repo_branches.branch = Array(ref_route_max_len).from(branch) orelse return null;│ │1637 return route; │ │1638 + } │ │1639 + if (std.mem.eql(u8, word, "delete")) { │ │1640 + _ = segments.next(); │ │1641 + return if (segments.next() == null) repoDeleteRoute(pair) else null; │ │1642 } │ │1643 return if (isNewTail(&segments)) .{ .repo_repo_new = Array(repo_route_max_len).from(pair) orelse return null } else null; │ │1644 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1957 a_r.confirm == b.repo_members.confirm, │ │1958 .repo_branches => |a_b| std.mem.eql(u8, a_b.name.slice(), b.repo_branches.name.slice()) and │ │1959 std.mem.eql(u8, a_b.branch.slice(), b.repo_branches.branch.slice()), │ │1960 + .repo_delete => |a_name| std.mem.eql(u8, a_name.slice(), b.repo_delete.slice()), │ │1961 .repo_user => |a_u| std.mem.eql(u8, a_u.name.slice(), b.repo_user.name.slice()) and a_u.tab.eql(b.repo_user.tab), │ │1962 .fork_patch => |a_f| std.mem.eql(u8, a_f.name.slice(), b.fork_patch.name.slice()) and std.mem.eql(u8, a_f.id.slice(), b.fork_patch.id.slice()),│ │1963 .fork_diff => |a_d| std.mem.eql(u8, a_d.fork.name.slice(), b.fork_diff.fork.name.slice()) and │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1975 std.mem.eql(u8, a_c.fork.id.slice(), b.fork_commits.fork.id.slice()) and │ │1976 std.mem.eql(u8, a_c.oid.slice(), b.fork_commits.oid.slice()) and │ │1977 a_c.message == b.fork_commits.message, │ │1978 + .fork_delete => |a_f| std.mem.eql(u8, a_f.name.slice(), b.fork_delete.name.slice()) and std.mem.eql(u8, a_f.id.slice(), b.fork_delete.id.slice()), │ │1979 .fork_repo_new => |a_f| std.mem.eql(u8, a_f.name.slice(), b.fork_repo_new.name.slice()) and std.mem.eql(u8, a_f.id.slice(), b.fork_repo_new.id.slice()),│ │1980 .fork_user_new => |a_f| std.mem.eql(u8, a_f.name.slice(), b.fork_user_new.name.slice()) and std.mem.eql(u8, a_f.id.slice(), b.fork_user_new.id.slice()),│ │1981 .fork_user => |a_u| std.mem.eql(u8, a_u.fork.name.slice(), b.fork_user.fork.name.slice()) and │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │2427 }; │ │2428 │ │2429 pub const AssignmentFailure = enum { not_found, not_an_email, already_assigned };│ │2430 + │ │2431 + pub const DeleteFailure = enum { wrong_confirm, wrong_password }; │ │2432 │ │2433 pub const KeyFailure = enum { │ │2434 invalid, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │2525 failure: AssignmentFailure, │ │2526 text: []const u8, │ │2527 }, │ │2528 + delete: struct { │ │2529 + failure: DeleteFailure, │ │2530 + // a page can hold two delete forms, so this names the failed one│ │2531 + target: std.meta.Tag(Delete.Target), │ │2532 + // the password is never retained │ │2533 + confirm: []const u8, │ │2534 + }, │ │2535 issue: struct { │ │2536 failure: ThreadFailure, │ │2537 fields: ?struct { │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯