╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │231 }); │ │232 } │ │233 │ │233 -pub fn mergePatch(data: *const Self, session: *ui.Session, allocator: std.mem.Allocator, id: []const u8, squash: bool) !void { │ │234 +pub fn mergePatch(data: *const Self, session: *ui.Session, allocator: std.mem.Allocator, id: []const u8, revision: pch.MergeRevision) !void {│ │235 const io = session.io orelse return error.NotFound; │ │236 const repos_dir = session.repos_dir orelse return error.NotFound; │ │237 const admin_repo = session.admin_repo orelse return error.NotFound; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │245 defer target_repo.deinit(io, allocator); │ │246 try pch.mergeAndRemoveFork(.{}, io, allocator, repos_dir, admin_repo, &target_repo, .{│ │247 .id = id_hex, │ │247 - .revision = if (squash) .squash else .source, │ │248 + .revision = revision, │ │249 .author = author, │ │250 .timestamp = @intCast(std.Io.Timestamp.now(io, .real).toSeconds()), │ │251 }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │604 else => revision.source_oid, │ │605 }; │ │606 if (item.record.event.status.kind() == .merged) continue; │ │607 + if (comptime repo_kind == .xit) { │ │608 + var moment = try repo.core.latestMoment(); │ │609 + const state = rp.Repo(.xit, repo_opts).State(.read_only){ .core = &repo.core, .extra = .{ .moment = &moment } };│ │610 + const id = try evt.parseEventId(item.id); │ │611 + item.mergeability = pch.readMergeability(repo_opts, state, io, arena, &id, item.record.event) catch .{}; │ │612 + } │ │613 const target_oid = try repo.readRef(io, .{ .kind = .head, .name = target_branch }); │ │614 item.no_changes = if (target_oid) |oid| std.mem.eql(u8, &oid, revision.source_oid) else false; │ │615 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭───────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 const builtin = @import("builtin"); │ │3 +const pch = @import("../../patch.zig"); │ │4 const evt = @import("../../event.zig"); │ │5 const ui = @import("../../ui.zig"); │ │6 const widget = @import("../widget.zig");│ ╰───────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │26 const SectionLabel = widget.SectionLabel; │ │27 const moveRowFocus = widget.moveRowFocus; │ │28 const wasm = builtin.target.cpu.arch == .wasm32; │ │29 + │ │30 +fn mergeBottomLabel(status: pch.Mergeability.Status) []const u8 { │ │31 + return switch (status) { │ │32 + .clean => "", │ │33 + .conflict => " conflict ", │ │34 + .unknown => " unavailable ", │ │35 + }; │ │36 +} │ │37 │ │38 // read the selected thread's conflicted fields and attribute each side to its│ │39 // event commit author │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │511 return listLink(page_arena, identity, status, encoded, ""); │ │512 } │ │513 │ │505 - fn addToolButton(allocator: std.mem.Allocator, row: *wgt.Box(Widget), label: []const u8, action: []const u8) !void { │ │506 - var button = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │514 + fn addToolButton(allocator: std.mem.Allocator, row: *wgt.Box(Widget), label: []const u8, bottom_label: []const u8, action: []const u8) !void { │ │515 + var button = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none, .bottom_label = bottom_label });│ │516 errdefer button.deinit(allocator); │ │517 button.getFocus().mode = .all; │ │518 button.getFocus().kind = .{ .custom = action }; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │510 - try row.children.put(allocator, button.getFocus().id, .{ .widget = .{ .text_box = button }, .rect = null, .min_size = .{ .width = try xitui.width.displayWidth(label) + 2, .height = null } }); │ │519 + try row.children.put(allocator, button.getFocus().id, .{ .widget = .{ .text_box = button }, .rect = null, .min_size = .{ .width = @max(try xitui.width.displayWidth(label), try xitui.width.displayWidth(bottom_label)) + 2, .height = null } });│ │520 } │ │521 │ │522 pub fn setEntry(self: *This, allocator: std.mem.Allocator, entry: Entry) !void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │542 │ │543 if (entryHasFork(entry) and self.session.data.current_page.parent() != .fork) { │ │544 const route = forkRoute(self.data.identity, entry.id) orelse return error.RouteTooLong; │ │536 - try addToolButton(allocator, row, "view fork", try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)})); │ │545 + try addToolButton(allocator, row, "view fork", "", try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)})); │ │546 const diff_route = ui.RoutablePage.forkDiffRoute(self.data.identity, entry.id, 0, "") orelse return error.RouteTooLong; │ │538 - try addToolButton(allocator, row, "view diff", try std.fmt.allocPrint(pa, "a:{s}", .{try diff_route.toUrl(self.session.page_arena)})); │ │547 + try addToolButton(allocator, row, "view diff", "", try std.fmt.allocPrint(pa, "a:{s}", .{try diff_route.toUrl(self.session.page_arena)}));│ │548 } │ │549 │ │550 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │556 if (comptime supports_merge) { │ │557 if (Data.canMerge(entry, self.session)) { │ │558 const route = mergeRoute(self.data.identity, entry.id) orelse return error.RouteTooLong; │ │550 - try addToolButton(allocator, row, "merge", try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)})); │ │559 + try addToolButton(allocator, row, "merge", mergeBottomLabel(entry.mergeability.status()), try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)}));│ │560 } │ │561 } │ │562 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │563 if (supports_drafts and entryDraft(entry)) { │ │564 const route = publishRoute(self.data.identity, entry.id) orelse return error.RouteTooLong; │ │556 - try addToolButton(allocator, row, "publish", try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)})); │ │565 + try addToolButton(allocator, row, "publish", "", try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)})); │ │566 if (self.session.data.user_id != null) { │ │567 const edit_route = ui.RoutablePage.repoThreadEditRoute(kind, self.data.identity, entry.id) orelse return error.RouteTooLong; │ │559 - try addToolButton(allocator, row, "edit", try std.fmt.allocPrint(pa, "a:{s}", .{try edit_route.toUrl(self.session.page_arena)})); │ │568 + try addToolButton(allocator, row, "edit", "", try std.fmt.allocPrint(pa, "a:{s}", .{try edit_route.toUrl(self.session.page_arena)}));│ │569 const remove_route = ui.RoutablePage.repoThreadRemoveRoute(kind, self.data.identity, entry.id, "") orelse return error.RouteTooLong; │ │561 - try addToolButton(allocator, row, "✕", try std.fmt.allocPrint(pa, "a:{s}", .{try remove_route.toUrl(self.session.page_arena)})); │ │570 + try addToolButton(allocator, row, "✕", "", try std.fmt.allocPrint(pa, "a:{s}", .{try remove_route.toUrl(self.session.page_arena)})); │ │571 } │ │572 } else { │ │573 if (!self.session.is_terminal and !entryConflicted(entry) and (self.session.data.is_local or self.session.data.user_id != null)) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯