╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │755 }; │ │756 field_count += 1; │ │757 } │ │759 - if (entry.target_branch.len != 0) { │ │760 - fields[field_count] = .{ │ │761 - .selector = "to", │ │762 - .text = entry.target_branch, │ │763 - .label = if (status_kind == .merged) " target branch this patch was merged into " else " target branch this patch will go to ",│ │764 - .bottom_label = if (status_kind == .merged) "" else " (set by the url you push to above) ", │ │765 - }; │ │766 - field_count += 1; │ │767 - } │ │758 + fields[field_count] = .{ │ │759 + .selector = "to", │ │760 + .text = target_branch, │ │761 + .label = if (status_kind == .merged) " target branch this patch was merged into " else " target branch this patch will go to ", │ │762 + }; │ │763 + field_count += 1; │ │764 │ │765 if (field_count > 0) { │ │766 var copyable_text = try ui.widget.CopyableText.init(allocator, session, fields[0..field_count]); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/ui/widget.zig│ ╰─────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1290 count += 1; │ │1291 } │ │1292 }, │ │1293 - .fork => |f| if (f.target_branch.len != 0) if (session.data.git_ssh_port) |port| { │ │1294 - const url = try std.fmt.allocPrint(aa, "ssh://localhost:{d}/fork/{s}/patch:{s}/branch:{s}", .{ port, f.identity, f.id, try ui.urlEncodeRef(aa, f.target_branch) });│ │1293 + .fork => |f| if (session.data.git_ssh_port) |port| { │ │1294 + const url = try std.fmt.allocPrint(aa, "ssh://localhost:{d}/fork/{s}/patch:{s}", .{ port, f.identity, f.id }); │ │1295 choices[count] = .{ │ │1296 .text = url, │ │1297 .copyable_text = try std.fmt.allocPrint(aa, "{s}git clone {s}", .{ session.data.git_ssh_prefix, url }), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 98 .ours = .{ .text = try revisionSummary(aa, ours.event.revision), .author = our_author }, │ │ 99 .theirs = .{ .text = try revisionSummary(aa, theirs.event.revision), .author = their_author },│ │100 }; │ │101 + } else if (std.mem.eql(u8, field, "target_branch")) { │ │102 + conflict.target_branch = .{ │ │103 + .ours = .{ .text = ours.event.target_branch, .author = our_author }, │ │104 + .theirs = .{ .text = theirs.event.target_branch, .author = their_author }, │ │105 + }; │ │106 } │ │107 } │ │108 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │111 │ │112 fn revisionSummary(allocator: std.mem.Allocator, revision_maybe: ?evt.Patch.Revision) ![]const u8 { │ │113 const revision = revision_maybe orelse return "(none)"; │ │109 - return std.fmt.allocPrint(allocator, "{s}\nsquash {s}\nsource {s}", .{ revision.target_ref, revision.squash_oid, revision.source_oid });│ │114 + return std.fmt.allocPrint(allocator, "squash {s}\nsource {s}", .{ revision.squash_oid, revision.source_oid }); │ │115 } │ │116 │ │117 fn readFieldOid( │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │1253 const title_field_index: usize = 0; │ │1254 const tags_field_index: usize = 1; │ │1255 const description_field_index: usize = 2; │ │1251 - const submit_field_index: usize = 3; │ │1256 + const target_branch_field_index: usize = 3; │ │1257 + const submit_field_index: usize = 3 + @as(usize, @intFromBool(supports_drafts));│ │1258 const comment_author_field_index: usize = 0; │ │1259 const comment_body_field_index: usize = 1; │ │1260 const comment_submit_field_index: usize = 2; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │1498 (if (data.selectedThread()) |entry| &entry.record else null) │ │1499 else │ │1500 null; │ │1495 - var form = try initThreadForm(allocator, session, action, record); │ │1501 + var form = try initThreadForm(allocator, session, data, action, record);│ │1502 errdefer form.deinit(allocator); │ │1503 try stack.children.put(allocator, form.getFocus().id, .{ .box = form });│ │1504 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1591 return box; │ │1592 } │ │1593 │ │1588 - // a thread form: title/tags/description inputs and a submit button, │ │1589 - // prefilled from `record` when given. its form: subtree makes the web │ │1590 - // renderer POST them to `action`'s route. │ │1591 - fn initThreadForm(allocator: std.mem.Allocator, session: *ui.Session, action: []const u8, record: ?*const Event.Record) !wgt.Box(Widget) { │ │1594 + // a thread form, plus the target branch for patches, prefilled from │ │1595 + // `record` when given. its form: subtree makes the web renderer POST │ │1596 + // the inputs to `action`'s route. │ │1597 + fn initThreadForm(allocator: std.mem.Allocator, session: *ui.Session, data: *const Self, action: []const u8, record: ?*const Event.Record) !wgt.Box(Widget) {│ │1598 var box = try wgt.Box(Widget).init(allocator, .{ .border_style = null, .direction = .vert }); │ │1599 errdefer box.deinit(allocator); │ │1600 box.getFocus().kind = .{ .custom = action }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1623 try box.children.put(allocator, description.getFocus().id, .{ .widget = .{ .text_input = description }, .rect = null, .min_size = null }); │ │1624 } │ │1625 │ │1626 + if (supports_drafts) { │ │1627 + var target = try wgt.TextInput.init(allocator, .{ .label = " target branch ", .name = "target_branch", .visible_width = null, .rounded_corners = true, .render_content = session.is_terminal });│ │1628 + errdefer target.deinit(allocator); │ │1629 + target.getFocus().focusable = true; │ │1630 + const content = if (record) |r| r.event.target_branch else data.default_target_branch; │ │1631 + try target.setContent(allocator, content); │ │1632 + try box.children.put(allocator, target.getFocus().id, .{ .widget = .{ .text_input = target }, .rect = null, .min_size = .{ .width = null, .height = 3 } }); │ │1633 + } │ │1634 + │ │1635 try addSubmitButtonLabeled(allocator, &box, if (supports_drafts and record == null) "submit draft" else "submit"); │ │1636 │ │1637 box.getFocus().child_id = box.children.keys()[title_field_index]; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1748 try addLabel(allocator, &box, "revision conflict:"); │ │1749 try addAtomicConflict(allocator, &box, session, data, "revision", fc); │ │1750 } │ │1751 + if (conflict.target_branch) |*fc| { │ │1752 + try addLabel(allocator, &box, "target branch conflict:"); │ │1753 + try addAtomicConflict(allocator, &box, session, data, "target_branch", fc);│ │1754 + } │ │1755 } │ │1756 │ │1757 if (conflict.description) |*desc| { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2473 defer allocator.free(tags); │ │2474 const description = try description_input.text(allocator); │ │2475 defer allocator.free(description); │ │2476 + const target_branch = if (comptime supports_drafts) try form.children.values()[target_branch_field_index].widget.text_input.text(allocator) else "";│ │2477 + defer if (comptime supports_drafts) allocator.free(target_branch); │ │2478 │ │2479 if (!Event.fieldsValid(title, tags)) return; │ │2480 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯