╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Fork/Header.zig│ ╰──────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │109 + // a single commit's diff names the commit under its tab │ │110 + const bottom_labels = [_][]const u8{ "", switch (session.data.current_page) { │ │111 + .fork_diff => |*d| if (d.oid.len == 0) "" else try ui.clippedBottomLabel(try aa.alloc(u8, ui.clipped_bottom_label_max_len), d.oid.slice()), │ │112 + else => "", │ │113 + }, "", "" }; │ │114 var selected_tab: ?usize = null; │ │115 │ │111 - for (routes, tags, labels) |route, tag, label| { │ │116 + for (routes, tags, labels, bottom_labels) |route, tag, label, bottom_label| { │ │117 const selected = current_tag == tag; │ │113 - var tab = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .round_corners = true, .wrap_kind = .none }); │ │118 + var tab = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .round_corners = true, .wrap_kind = .none, .bottom_label = bottom_label });│ │119 errdefer tab.deinit(allocator); │ │120 tab.getFocus().mode = .all; │ │121 tab.getFocus().kind = .{ .custom = try ui.inPageTabLink(session, route, selected) }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │89 const files_find: []const u8 = switch (route) { │ │90 .repo_files => |*f| f.find.slice(), │ │91 else => "", │ │92 - }; │ │93 - // what the commits view's pane shows for the commit it walks from: a diff │ │94 - // window (with the file it's filtered to) or that commit's message. │ │95 - const commits_content: ui.RoutablePage.RepoCommitsRoute.Content = switch (route) {│ │96 - .repo_commits => |c| c.content, │ │97 - else => .{ .diff = .{} }, │ │92 }; │ │93 + // the commits view's pane shows the whole message of the commit it walks from │ │94 + const commits_message = route == .repo_commits and route.repo_commits.message; │ │95 const commits_base_oid: []const u8 = switch (route) { │ │96 .repo_commits => |*c| c.base_oid.slice(), │ │97 else => "", │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │312 else if (patchrev_id.len != 0) diff: { │ │313 const diff_route = ui.RoutablePage.repoPatchRevDiffRoute(repo_identity.identity, patchrev_id, 0, "") orelse return error.RouteTooLong; │ │314 break :diff .{ .diff = try Diff.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, diff_route.repo_diff) }; │ │319 - } else .{ .commits = try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, session.haxy_moment, handle, ref_or_oid, ref_value, commits_content, base_oid, commits_search, commits_from) };│ │315 + } else .{ .commits = try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, session.haxy_moment, handle, ref_or_oid, ref_value, commits_message, base_oid, commits_search, commits_from) };│ │316 const target_branch = if (files_data.ref_or_oid == .branch) files_data.ref_or_oid_value else ""; │ │317 break :blk .{ │ │318 files_data, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │331 const aa = arena.allocator(); │ │332 break :blk .{ │ │333 try Files.emptyResult(aa, handle, requested_ref_or_oid orelse .branch, requested_ref_value, files_dir), │ │338 - Changes{ .commits = try Commits.emptyResult(aa, handle, requested_ref_or_oid orelse .branch, requested_ref_value, commits_content, commits_base_oid) }, │ │334 + Changes{ .commits = try Commits.emptyResult(aa, handle, requested_ref_or_oid orelse .branch, requested_ref_value, commits_base_oid) }, │ │335 try Refs.emptyResult(arena, repo_identity.identity, refs_kind, refs_from, refs_search), │ │336 try Issues.emptyResult(aa, repo_identity.identity, issues_label, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view), │ │337 try Patches.emptyResult(aa, repo_identity.identity, patches_label, patches_search, patches_selected, patches_comment, patches_comments_start, patches_theirs, patches_view),│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 -const builtin = @import("builtin"); │ │2 const evt = @import("../../event.zig");│ │3 const ui = @import("../../ui.zig"); │ │4 const xit = @import("xit"); │ ╰──────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │23 // limit. │ │24 const max_message_size = 100 * 1024; │ │25 │ │27 -// one commit on the current page, with its diff against its first parent │ │28 -// pre-rendered up to the budget so the web client can show it without a repo.│ │26 +// one commit on the current page. │ │27 pub const Commit = struct { │ │28 oid: []const u8, │ │29 + // what its diff is against: the first parent, all zeros for a root commit│ │30 + parent_oid: []const u8, │ │31 date: []const u8, // "YYYY-MM-DD" │ │32 message: []const u8, // trimmed, may be multi-line │ │33 // whether `message` is a shortened preview. │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │40 // whether it has a second parent. │ │41 merge: bool = false, │ │42 stats: ?xit.patch.CommitStats = null, │ │43 - window: Diff.Window = .{}, │ │43 }; │ │44 │ │45 // where links and clone commands for this repository are rooted, and who views it.│ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │53 commits: []const Commit, │ │54 // the first oid of the next page, or null when this is the last page. │ │55 next_start: ?[]const u8, │ │57 -// what the pane shows for the commit the log walks from. │ │58 -content: Content = .{ .diff = .{} }, │ │56 +// the pane shows the whole message of the commit the log walks from. │ │57 +message: bool = false, │ │58 // the decoded query this list holds the results of, or null for a plain log.│ │59 search: ?[]const u8 = null, │ │60 // whether the viewed ref has a commit index, so the search box shows and a │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │67 no_commits: bool = false, │ │68 │ │69 const Self = @This(); │ │71 - │ │72 -// the diff and the message are alternatives, so a filtered diff can't also be│ │73 -// a message. the message page reads up to the safety limit above. │ │74 -pub const Content = union(enum) { │ │75 - diff: struct { │ │76 - // the file the top commit's diff is filtered to ("" = every file). │ │77 - path: []const u8 = "", │ │78 - }, │ │79 - message, │ │80 -}; │ │70 │ │71 // walk the log for an opened repo. generic over the repo's backend and hash │ │83 -// kind so the oid buffers and diff types it threads through match the repo's │ │84 -// opts. `content` is what the walk root's pane shows, the only commit any of │ │85 -// it applies to. walks with the arena's backing allocator (transient; the │ │86 -// commits we keep are duped into the page arena so they outlive it). │ │72 +// kind so the oid buffers it threads through match the repo's opts. `message`│ │73 +// reads the walk root's message whole, up to the safety limit above. walks │ │74 +// with the arena's backing allocator (transient; the commits we keep are │ │75 +// duped into the page arena so they outlive it). │ │76 pub fn init( │ │77 comptime repo_kind: rp.RepoKind, │ │78 comptime repo_opts: rp.RepoOpts(repo_kind), │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │ 86 handle: ui.RepoHandle, │ │ 87 requested_ref_or_oid: ?ui.RoutablePage.RefOrOid, │ │ 88 requested_value: []const u8, │ │100 - content: ui.RoutablePage.RepoCommitsRoute.Content,│ │ 89 + message: bool, │ │ 90 base_oid: []const u8, │ │ 91 search: []const u8, │ │ 92 from: []const u8, │ ╰───────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯