╭ changed ──────╮ │src/test/ui.zig│ ╰───────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 4 const Commits = @import("../ui/Repo/Commits.zig"); │ │ 5 const Events = @import("../ui/Repo/Events.zig"); │ │ 6 const xit = @import("xit"); │ │ 7 + │ │ 8 +test "preloaded thread forms receive typing after switching tabs" { │ │ 9 + const allocator = std.testing.allocator; │ │10 + var arena = std.heap.ArenaAllocator.init(allocator); │ │11 + defer arena.deinit(); │ │12 + var session = ui.Session{ .arena = &arena, .page_arena = &arena, .is_terminal = true, .data = .{ .host_kind = .local } }; │ │13 + session.data.current_page = ui.RoutablePage.repoIssuesRoute("", .open, "", "") orelse return error.BadRoute; │ │14 + const data = try ui.Repo.Issues.emptyResult(arena.allocator(), "", "", "", "", 0, "", .open); │ │15 + var root = ui.Widget{ .repo_issues = try ui.Repo.Issues.View.init(allocator, &data, &session) }; │ │16 + defer root.deinit(allocator); │ │17 + const focus = root.getFocus(); │ │18 + const constraint = xit.xitui.layout.Constraint{ │ │19 + .min_size = .{ .width = null, .height = null }, │ │20 + .max_size = .{ .width = 100, .height = 40 }, │ │21 + }; │ │22 + try root.build(allocator, constraint, focus); │ │23 + │ │24 + // switch to the preloaded new tab without recreating the page │ │25 + for ([_]xit.xitui.input.Key{ .arrow_right, .arrow_right, .arrow_right, .arrow_down }) |key| { │ │26 + try ui.inputKey(allocator, &root, key, &session); │ │27 + try root.build(allocator, constraint, focus); │ │28 + } │ │29 + for ([_][]const u8{ "title", "tags", "description" }) |name| { │ │30 + const input = session.text_inputs.get(focus.grandchild_id orelse return error.NoFocus) orelse return error.MissingInput;│ │31 + try std.testing.expectEqualStrings(name, input.options.name); │ │32 + try ui.inputKey(allocator, &root, .{ .codepoint = 'x' }, &session); │ │33 + try root.build(allocator, constraint, focus); │ │34 + const value = try input.text(allocator); │ │35 + defer allocator.free(value); │ │36 + try std.testing.expectEqualStrings("x", value); │ │37 + try ui.inputKey(allocator, &root, .tab, &session); │ │38 + try root.build(allocator, constraint, focus); │ │39 + } │ │40 +} │ │41 │ │42 test "web controls omit hidden inputs but retain off-screen inputs" { │ │43 const wgt = xit.xitui.widget; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │1988 } │ │1989 │ │1990 fn threadForm(self: *This) ?*wgt.Box(Widget) { │ │1991 + if (supports_conflicts and self.data.view == .resolve) return null;│ │1992 return switch (self.data.view) { │ │1992 - .new, .edit => self.formBox(), │ │1993 - else => null, │ │1993 + .new_comment, .edit_comment => null, │ │1994 + else => self.formBox(), │ │1995 }; │ │1996 } │ │1997 │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2134 if (form.children.values()[source_field_index].widget == .patch_source) { │ │2135 const source = &form.children.values()[source_field_index].widget.patch_source; │ │2136 source.field().options.label = if (failure == .invalid_source_branch) " source branch (not found) " else if (failure == .unrelated_branches) " source branch (unrelated) " else " source branch "; │ │2136 - const submit = &form.children.values()[form.children.count() - 1].widget.submit_button; │ │2137 + const submit = &form.children.values()[form.children.count() - 2].widget.submit_button; │ │2138 try submit.setLabel(allocator, if (source.existing) "submit patch" else "submit draft"); │ │2139 } │ │2139 - const target_branch_field_index = form.children.count() - 2; │ │2140 + const target_branch_field_index = form.children.count() - 3; │ │2141 form.children.values()[target_branch_field_index].widget.text_input.options.label = │ │2142 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 ";│ │2143 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │2243 const form = self.threadForm() orelse return; │ │2244 const cid = form.getFocus().child_id orelse return; │ │2245 const cur = form.children.getIndex(cid) orelse return;│ │2245 - const submit_field_index = form.children.count() - 1; │ │2246 + const submit_field_index = form.children.count() - 2; │ │2247 const child = &form.children.values()[cur]; │ │2248 │ │2249 if (cur == description_field_index) { │ ╰────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2525 const author = (try self.session.eventAuthor()) orelse return; │ │2526 │ │2527 const form = self.threadForm() orelse return; │ │2527 - const target_branch_field_index = form.children.count() - 2; │ │2528 + const target_branch_field_index = form.children.count() - 3; │ │2529 const title_input = &form.children.values()[title_field_index].widget.text_input; │ │2530 const tags_input = &form.children.values()[tags_field_index].widget.text_input; │ │2531 const description_input = &form.children.values()[description_field_index].widget.text_input;│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2605 const entry = self.data.selectedThread() orelse return; │ │2606 │ │2607 const form = self.threadForm() orelse return; │ │2607 - const target_branch_field_index = form.children.count() - 2; │ │2608 + const target_branch_field_index = form.children.count() - 3; │ │2609 const title_input = &form.children.values()[title_field_index].widget.text_input; │ │2610 const tags_input = &form.children.values()[tags_field_index].widget.text_input; │ │2611 const description_input = &form.children.values()[description_field_index].widget.text_input;│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯