╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │399 try stack.children.put(allocator, tf.getFocus().id, .{ .tag_flow = tf }); │ │400 } │ │401 │ │390 - // the new-issue form │ │402 + // the new-issue form, or — on an edit url — the edit form in its │ │403 + // place, prefilled with the selected issue's content. │ │404 { │ │392 - var form = try initNewForm(allocator, session, data); │ │405 + const aa = session.page_arena.allocator(); │ │406 + const action = if (data.view == .edit) │ │407 + (if (data.identity.len == 0) │ │408 + try std.fmt.allocPrint(aa, "form:/issues/{s}/edit", .{data.selected_id}) │ │409 + else │ │410 + try std.fmt.allocPrint(aa, "form:/repo/{s}/issues/{s}/edit", .{ data.identity, data.selected_id }))│ │411 + else if (data.identity.len == 0) │ │412 + "form:/issue" │ │413 + else │ │414 + try std.fmt.allocPrint(aa, "form:/repo/{s}/issue", .{data.identity}); │ │415 + const issue = if (data.view == .edit) │ │416 + (if (data.selectedIssue()) |entry| &entry.issue else null) │ │417 + else │ │418 + null; │ │419 + var form = try initIssueForm(allocator, action, issue); │ │420 errdefer form.deinit(allocator); │ │421 try stack.children.put(allocator, form.getFocus().id, .{ .box = form }); │ │422 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │503 return box; │ │504 } │ │505 │ │479 - // the new-issue form: title/tags/description inputs and a submit button. │ │480 - // its form: subtree makes the web overlay wrap them in a <form> POSTing to │ │481 - // the issue route. │ │482 - fn initNewForm(allocator: std.mem.Allocator, session: *ui.Session, data: *const Self) !wgt.Box(ui.Widget) { │ │506 + // an issue form: title/tags/description inputs and a submit button, │ │507 + // prefilled from `issue` when given. its form: subtree makes the web │ │508 + // overlay wrap them in a <form> POSTing to `action`'s route. │ │509 + fn initIssueForm(allocator: std.mem.Allocator, action: []const u8, issue: ?*const evt.Issue) !wgt.Box(ui.Widget) { │ │510 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .vert }); │ │511 errdefer box.deinit(allocator); │ │485 - box.getFocus().kind = .{ .custom = if (data.identity.len == 0) │ │486 - "form:/issue" │ │487 - else │ │488 - try std.fmt.allocPrint(session.page_arena.allocator(), "form:/repo/{s}/issue", .{data.identity}) }; │ │512 + box.getFocus().kind = .{ .custom = action }; │ │513 │ │514 { │ │515 var title = try wgt.TextInput(ui.Widget).init(allocator, .{ .label = " title ", .name = "title", .visible_width = null, .rounded_corners = true, .render_content = !wasm });│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │516 errdefer title.deinit(allocator); │ │517 title.getFocus().focusable = true; │ │518 + if (issue) |i| try title.setContent(allocator, i.title); │ │519 try box.children.put(allocator, title.getFocus().id, .{ .widget = .{ .text_input = title }, .rect = null, .min_size = null });│ │520 } │ │521 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │523 var tags = try wgt.TextInput(ui.Widget).init(allocator, .{ .label = " tags (separate with spaces) ", .name = "tags", .visible_width = null, .rounded_corners = true, .render_content = !wasm });│ │524 errdefer tags.deinit(allocator); │ │525 tags.getFocus().focusable = true; │ │526 + if (issue) |i| try tags.setContent(allocator, i.tags); │ │527 try box.children.put(allocator, tags.getFocus().id, .{ .widget = .{ .text_input = tags }, .rect = null, .min_size = null }); │ │528 } │ │529 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │531 var description = try wgt.TextInput(ui.Widget).init(allocator, .{ .label = " description ", .name = "description", .visible_width = null, .rounded_corners = true, .render_content = !wasm, .multiline = true, .visible_height = 5 });│ │532 errdefer description.deinit(allocator); │ │533 description.getFocus().focusable = true; │ │534 + if (issue) |i| try description.setContent(allocator, i.description); │ │535 try box.children.put(allocator, description.getFocus().id, .{ .widget = .{ .text_input = description }, .rect = null, .min_size = null }); │ │536 } │ │537 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │587 return &self.viewStack().children.values()[tags_view_index].tag_flow;│ │588 } │ │589 │ │563 - // the new-issue form inside the stack. │ │564 - fn newForm(self: *View) *wgt.Box(ui.Widget) { │ │565 - return &self.viewStack().children.values()[new_view_index].box; │ │590 + // the new-issue (or edit) form inside the stack. │ │591 + fn issueForm(self: *View) *wgt.Box(ui.Widget) { │ │592 + return &self.viewStack().children.values()[form_view_index].box; │ │593 } │ │594 │ │595 fn listScroll(self: *View, index: usize) *wgt.Scroll(ui.Widget) { │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │653 return self.stackSelectedIndex() == tags_view_index; │ │654 } │ │655 │ │629 - fn newViewActive(self: *View) bool { │ │656 + fn formViewActive(self: *View) bool { │ │657 if (self.headerActive()) return false; │ │631 - return self.stackSelectedIndex() == new_view_index; │ │658 + return self.stackSelectedIndex() == form_view_index; │ │659 } │ │660 │ │661 // the selected issue's index, or null when a window-navigation row is│ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │680 if (self.header().getSelectedIndex()) |index| { │ │681 const stack = self.viewStack(); │ │682 stack.getFocus().child_id = stack.children.keys()[index]; │ │656 - self.session.data.current_page = (if (index == viewIndex(self.data.view) and self.data.selected_id.len != 0)│ │683 + self.session.data.current_page = (if (index == form_view_index and self.data.view == .edit) │ │684 + ui.RoutablePage.repoIssuesEditRoute(self.data.identity, self.data.selected_id) │ │685 + else if (index == viewIndex(self.data.view) and self.data.selected_id.len != 0) │ │686 ui.RoutablePage.repoIssuesRoute(self.data.identity, .open, self.data.tag, self.data.selected_id) │ │687 else if (index == tags_view_index) │ │688 ui.RoutablePage.repoIssuesTagsRoute(self.data.identity, self.data.tag) │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │660 - else if (index == new_view_index) │ │689 + else if (index == form_view_index) │ │690 ui.RoutablePage.repoIssuesNewRoute(self.data.identity) │ │691 else │ │692 ui.RoutablePage.repoIssuesRoute(self.data.identity, splitStatus(index), self.data.tag, "")) orelse self.session.data.current_page;│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │740 // refresh the form inputs' entries in the session's focus-id -> input │ │741 // map with this frame's addresses, so the web/wasm form handling can │ │742 // find them by focus id │ │714 - const form = self.newForm(); │ │743 + const form = self.issueForm(); │ │744 const inputs_arena = self.session.arena.allocator(); │ │745 for (form.children.values()) |*child| switch (child.widget) { │ │746 .text_input => |*ti| try self.session.text_inputs.put(inputs_arena, ti.getFocus().id, ti),│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯