╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────╮ │1267 const detail_index: usize = 1; │ │1268 const list_max_width: usize = 35; │ │1269 const detail_min_width: usize = 40; │ │1270 - // indices within the thread form. │ │1271 - const title_field_index: usize = 0; │ │1272 - const tags_field_index: usize = 1; │ │1273 - const description_field_index: usize = 2; │ │1274 - const source_field_index: usize = 3; │ │1275 - const comment_author_field_index: usize = 0;│ │1276 - const comment_body_field_index: usize = 1; │ │1277 - const comment_submit_field_index: usize = 2;│ │1270 │ │1271 pub fn viewIndex(view: ViewKind) usize { │ │1272 const name = @tagName(view); │ ╰──────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1625 else if (record) |r| │ │1626 try title.setContent(allocator, r.event.title); │ │1627 try box.children.put(allocator, title.getFocus().id, .{ .widget = .{ .text_input = title }, .rect = null, .min_size = .{ .width = null, .height = 3 } });│ │1628 + box.getFocus().child_id = title.getFocus().id; │ │1629 } │ │1630 │ │1631 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1667 │ │1668 try addSubmitButtonLabeled(allocator, &box, if (supports_drafts and record == null) "submit draft" else "submit");│ │1669 │ │1677 - box.getFocus().child_id = box.children.keys()[title_field_index]; │ │1670 return box; │ │1671 } │ │1672 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1681 parent.options.label = " replying to "; │ │1682 parent.getFocus().kind = .{ .custom = try std.fmt.allocPrint(session.page_arena.allocator(), "a:{s}", .{try parent_route.toUrl(session.page_arena)}) }; │ │1683 try box.children.put(allocator, parent.getFocus().id, .{ .widget = .{ .text_box = parent }, .rect = null, .min_size = .{ .width = null, .height = 3 } });│ │1684 + box.getFocus().child_id = parent.getFocus().id; │ │1685 } │ │1686 │ │1687 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │1702 } │ │1703 │ │1704 try addSubmitButtonLabeled(allocator, &box, "submit"); │ │1712 - box.getFocus().child_id = box.children.keys()[comment_author_field_index];│ │1705 return box; │ │1706 } │ │1707 │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1987 }; │ │1988 } │ │1989 │ │1990 + fn formField(form: *wgt.Box(Widget), name: []const u8) !*wgt.TextInput { │ │1991 + for (form.children.values()) |*child| switch (child.widget) { │ │1992 + .text_input => |*text_input| if (std.mem.eql(u8, text_input.options.name, name)) return text_input, │ │1993 + else => {}, │ │1994 + }; │ │1995 + return error.MissingFormField; │ │1996 + } │ │1997 + │ │1998 + fn formWidget(form: *wgt.Box(Widget), comptime widget_kind: std.meta.Tag(Widget)) ?*@FieldType(Widget, @tagName(widget_kind)) {│ │1999 + for (form.children.values()) |*child| { │ │2000 + if (child.widget == widget_kind) return &@field(child.widget, @tagName(widget_kind)); │ │2001 + } │ │2002 + return null; │ │2003 + } │ │2004 + │ │2005 fn confirmationForm(self: *This) ?*wgt.Box(Widget) { │ │2006 return switch (self.viewStack().children.values()[form_view_index]) { │ │2007 .center => |*center| switch (center.child.*) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2136 // find them by focus id │ │2137 if (self.threadForm()) |form| { │ │2138 const failure = if (self.session.formFeedback(feedback_tag)) |saved| saved.failure else null; │ │2132 - form.children.values()[title_field_index].widget.text_input.options.label = if (failure == .required_title) " title (required) " else " title "; │ │2139 + (try formField(form, "title")).options.label = if (failure == .required_title) " title (required) " else " title "; │ │2140 if (comptime supports_drafts) { │ │2134 - if (form.children.values()[source_field_index].widget == .patch_source) { │ │2135 - const source = &form.children.values()[source_field_index].widget.patch_source; │ │2141 + if (formWidget(form, .patch_source)) |source| { │ │2142 source.field().options.label = if (failure == .invalid_source_branch) " source branch (not found) " else if (failure == .unrelated_branches) " source branch (unrelated) " else " source branch "; │ │2137 - const submit = &form.children.values()[form.children.count() - 2].widget.submit_button; │ │2143 + const submit = formWidget(form, .submit_button) orelse return error.MissingFormField; │ │2144 try submit.setLabel(allocator, if (source.existing) "submit patch" else "submit draft"); │ │2145 } │ │2140 - const target_branch_field_index = form.children.count() - 3; │ │2141 - form.children.values()[target_branch_field_index].widget.text_input.options.label = │ │2146 + (try formField(form, "target_branch")).options.label = │ │2147 if (failure == .invalid_target_branch) " target branch (not found) " else if (self.data.view == .edit and failure == .unrelated_branches) " target branch (unrelated to source) " else if (self.data.view == .edit and failure == .invalid_source_branch) " target branch (source branch not found) " else " target branch ";│ │2148 } │ │2149 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2190 try self.confirmationFormInput(allocator, key, root_focus); │ │2191 } else if (supports_conflicts and self.data.view == .resolve) { │ │2192 try self.resolveInput(allocator, key, root_focus); │ │2188 - } else if (self.data.view == .new_comment or self.data.view == .edit_comment) {│ │2189 - try self.commentFormInput(allocator, key, root_focus); │ │2193 } else { │ │2194 try self.formInput(allocator, key, root_focus); │ │2195 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2243 } │ │2244 │ │2245 fn formInput(self: *This, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { │ │2243 - const form = self.threadForm() orelse return; │ │2246 + const form = self.formBox() orelse return; │ │2247 const cid = form.getFocus().child_id orelse return; │ │2248 const cur = form.children.getIndex(cid) orelse return; │ │2246 - const submit_field_index = form.children.count() - 2; │ │2249 const child = &form.children.values()[cur]; │ │2250 │ │2249 - if (cur == description_field_index) { │ │2250 - if (try multilineKeepsKey(&child.widget.text_input, allocator, key)) │ │2251 + if (child.widget == .text_input) { │ │2252 + const text_input = &child.widget.text_input; │ │2253 + if (text_input.options.multiline and try multilineKeepsKey(text_input, allocator, key))│ │2254 return child.widget.input(allocator, key, root_focus); │ │2255 } │ │2256 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2257 + const on_submit = child.widget == .submit_button; │ │2258 switch (key) { │ │2255 - .arrow_up, .back_tab => return if (cur > 0) │ │2256 - root_focus.setFocus(form.children.keys()[cur - 1]) │ │2259 + .arrow_up, .back_tab => return if (formStep(form, cur, false)) |i| │ │2260 + root_focus.setFocus(form.children.keys()[i]) │ │2261 else │ │2262 self.focusHeader(root_focus), │ │2259 - .arrow_down, .tab => return if (cur < submit_field_index) root_focus.setFocus(form.children.keys()[cur + 1]), │ │2260 - .enter => if (cur == submit_field_index) return self.submitForm(allocator), │ │2261 - .mouse => |mouse| if (cur == submit_field_index) { │ │2263 + .arrow_down, .tab => return if (formStep(form, cur, true)) |i| root_focus.setFocus(form.children.keys()[i]), │ │2264 + .enter => if (on_submit) return self.submitForm(allocator), │ │2265 + .mouse => |mouse| if (on_submit) { │ │2266 if (inp.leftClickOn(root_focus, child.widget.submit_button.buttonId(), mouse)) return self.submitForm(allocator);│ │2267 }, │ │2268 else => {}, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯