╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 977 } │ │ 978 if (!params.only(&.{.start})) return null; │ │ 979 return repoThreadCommentsRoute(.issue, pair, issue_id, params.start() orelse return null); │ │ 980 + } │ │ 981 + if (std.mem.startsWith(u8, tab, patch_seg)) { │ │ 982 + const patch_id = tab[patch_seg.len..]; │ │ 983 + if (patch_id.len == 0) return null; │ │ 984 + if (segments.peek()) |tail| { │ │ 985 + if (std.mem.startsWith(u8, tail, comment_seg)) { │ │ 986 + _ = segments.next(); │ │ 987 + const comment_id = tail[comment_seg.len..]; │ │ 988 + if (comment_id.len == 0) return null; │ │ 989 + const word = params.scanTail(&segments) catch return null; │ │ 990 + if (word) |last| { │ │ 991 + if (!params.only(&.{})) return null; │ │ 992 + if (std.mem.eql(u8, last, "new")) return repoThreadCommentNewRoute(.patch, pair, patch_id, comment_id); │ │ 993 + if (std.mem.eql(u8, last, "edit")) return repoThreadCommentEditRoute(.patch, pair, patch_id, comment_id); │ │ 994 + if (std.mem.eql(u8, last, "remove")) return repoThreadRemoveRoute(.patch, pair, patch_id, comment_id); │ │ 995 + return null; │ │ 996 + } │ │ 997 + if (!params.only(&.{.start})) return null; │ │ 998 + return repoThreadCommentRoute(.patch, pair, patch_id, comment_id, params.start() orelse return null); │ │ 999 + } │ │1000 + } │ │1001 + const word = params.scanTail(&segments) catch return null; │ │1002 + if (word) |tail| { │ │1003 + if (std.mem.eql(u8, tail, "new")) return if (params.only(&.{})) repoThreadCommentNewRoute(.patch, pair, patch_id, "") else null; │ │1004 + if (std.mem.eql(u8, tail, "edit")) return if (params.only(&.{})) repoThreadEditRoute(.patch, pair, patch_id) else null; │ │1005 + if (std.mem.eql(u8, tail, "remove")) return if (params.only(&.{})) repoThreadRemoveRoute(.patch, pair, patch_id, "") else null; │ │1006 + if (std.mem.eql(u8, tail, "description")) return if (params.only(&.{})) repoThreadDescriptionRoute(.patch, pair, patch_id) else null;│ │1007 + if (std.mem.eql(u8, tail, "resolve")) { │ │1008 + if (!params.only(&.{.theirs})) return null; │ │1009 + return repoPatchesResolveRoute(pair, patch_id, params.values.get(.theirs) orelse ""); │ │1010 + } │ │1011 + return null; │ │1012 + } │ │1013 + if (!params.only(&.{.start})) return null; │ │1014 + return repoThreadCommentsRoute(.patch, pair, patch_id, params.start() orelse return null); │ │1015 } │ │1016 if (std.mem.startsWith(u8, tab, discuss_seg)) { │ │1017 const discussion_id = tab[discuss_seg.len..]; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1059 if (std.meta.stringToEnum(evt.Issue.Status, w)) |status| return repoIssuesRoute(pair, status, tag_value, ""); │ │1060 if (std.mem.eql(u8, w, "tags")) return repoThreadTagsRoute(.issue, pair, tag_value); │ │1061 if (std.mem.eql(u8, w, "new")) return if (tag_value.len == 0) repoThreadNewRoute(.issue, pair) else null; │ │1062 + return null; │ │1063 + } │ │1064 + if (std.mem.eql(u8, tab, "patches")) { │ │1065 + const word = params.scanTail(&segments) catch return null; │ │1066 + const tag_value = params.values.get(.tag) orelse ""; │ │1067 + const view = word orelse return if (params.only(&.{})) repoPatchesRoute(pair, .open, "", "") else null; │ │1068 + if (std.mem.eql(u8, view, "conflicts")) { │ │1069 + if (!params.only(&.{.start})) return null; │ │1070 + return repoPatchesConflictsRoute(pair, params.values.get(.start) orelse ""); │ │1071 + } │ │1072 + if (!params.only(&.{.tag})) return null; │ │1073 + if (std.meta.stringToEnum(evt.Patch.Status, view)) |status| return repoPatchesRoute(pair, status, tag_value, "");│ │1074 + if (std.mem.eql(u8, view, "tags")) return repoThreadTagsRoute(.patch, pair, tag_value); │ │1075 + if (std.mem.eql(u8, view, "new")) return if (tag_value.len == 0) repoThreadNewRoute(.patch, pair) else null; │ │1076 + if (std.mem.eql(u8, view, "drafts")) return if (tag_value.len == 0) repoPatchesDraftsRoute(pair) else null; │ │1077 return null; │ │1078 } │ │1079 if (std.mem.eql(u8, tab, "discussions")) { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1133 .home_users => |a_start| a_start == b.home_users, │ │1134 .home_repos => |a_start| a_start == b.home_repos, │ │1135 .user_repos => |a_u| std.mem.eql(u8, a_u.name.slice(), b.user_repos.name.slice()) and a_u.start == b.user_repos.start,│ │1136 + .user_forks => |a_u| std.mem.eql(u8, a_u.name.slice(), b.user_forks.name.slice()) and a_u.start == b.user_forks.start,│ │1137 .user_settings => |a_name| std.mem.eql(u8, a_name.slice(), b.user_settings.slice()), │ │1138 .user_auth => |a_name| std.mem.eql(u8, a_name.slice(), b.user_auth.slice()), │ │1139 .repo_files => |a_f| std.mem.eql(u8, a_f.name.slice(), b.repo_files.name.slice()) and │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1165 a_t.view == b.repo_discussions.view and │ │1166 a_t.comments_start == b.repo_discussions.comments_start and │ │1167 std.mem.eql(u8, a_t.comment.slice(), b.repo_discussions.comment.slice()), │ │1168 + .repo_patches => |a_p| std.mem.eql(u8, a_p.name.slice(), b.repo_patches.name.slice()) and│ │1169 + std.mem.eql(u8, a_p.tag.slice(), b.repo_patches.tag.slice()) and │ │1170 + std.mem.eql(u8, a_p.selected.slice(), b.repo_patches.selected.slice()) and │ │1171 + std.mem.eql(u8, a_p.theirs.slice(), b.repo_patches.theirs.slice()) and │ │1172 + a_p.view == b.repo_patches.view and │ │1173 + a_p.comments_start == b.repo_patches.comments_start and │ │1174 + std.mem.eql(u8, a_p.comment.slice(), b.repo_patches.comment.slice()), │ │1175 .repo_events => |a_e| std.mem.eql(u8, a_e.name.slice(), b.repo_events.name.slice()) and │ │1176 a_e.view == b.repo_events.view and │ │1177 a_e.kind == b.repo_events.kind and │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1201 .user_repos => |bb| std.mem.eql(u8, aa.name.slice(), bb.name.slice()) and aa.start != bb.start,│ │1202 else => false, │ │1203 }, │ │1204 + .user_forks => |aa| switch (b) { │ │1205 + .user_forks => |bb| std.mem.eql(u8, aa.name.slice(), bb.name.slice()) and aa.start != bb.start,│ │1206 + else => false, │ │1207 + }, │ │1208 else => false, │ │1209 }; │ │1210 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │1368 // during page construction. both null on wasm, which has no filesystem and │ │1369 // rebuilds pages from the serialized snapshot rather than from disk. │ │1370 io: ?std.Io = null, │ │1371 + admin_repo: ?*rp.Repo(.xit, evt.admin_repo_opts) = null, │ │1372 repos_dir: ?[]const u8 = null, │ │1373 // the single on-disk repo this session views, when running in local mode │ │1374 // (haxy invoked with no arguments inside a repo). null on the server paths,│ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │1449 // allocations land in the session arena. on the web path that's the│ │1450 // intended behavior, since the whole arena is per-request. │ │1451 .page_arena = arena, │ │1452 + .admin_repo = repo, │ │1453 .haxy_moment = try evt.currentMoment(evt.admin_repo_opts, repo), │ │1454 }; │ │1455 try session.loadUser(); │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │2046 repo_files_header: Repo.Files.Header.View, │ │2047 repo_commits_header: Repo.Commits.Header.View, │ │2048 repo_issues_header: Repo.Issues.Header, │ │2049 + repo_patches_header: Repo.Patches.Header, │ │2050 repo_discussions_header: Repo.Discussions.Header,│ │2051 repo_files: Repo.Files.View, │ │2052 repo_commits: Repo.Commits.View, │ ╰───────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────╮ │2053 repo_refs: Repo.Refs.View, │ │2054 repo_issues: Repo.Issues.View, │ │2055 + repo_patches: Repo.Patches.View, │ │2056 repo_discussions: Repo.Discussions.View, │ │2057 repo_events_header: Repo.Events.Header.View,│ │2058 repo_events: Repo.Events.View, │ ╰──────────────────────────────────────────────────────╯ ╭ changed ──────────╮ │src/ui/CloneUrl.zig│ ╰───────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 9 const Grid = xitui.grid.Grid; │ │10 const Focus = xitui.focus.Focus; │ │11 const inp = @import("input.zig"); │ │12 + │ │13 +const debug_ssh_prefix = "GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR' \\\r\n";│ │14 │ │15 pub const View = struct { │ │16 box: wgt.Box(ui.Widget), │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯