╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │412 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ │413 self.clearGrid(); │ │414 │ │415 + // each sub header tab maps 1:1 to a stack child by position. │ │416 + if (self.subHeader().getSelectedIndex()) |index| { │ │417 + const stack = self.viewStack(); │ │418 + stack.getFocus().child_id = stack.children.keys()[index]; │ │419 + } │ │420 + │ │421 // swap the detail pane to the selected issue when it changes. │ │422 try self.refreshDetail(allocator); │ │423 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │455 } │ │456 } │ │457 if (self.tagFlow()) |tf| tf.selected = self.tagsFocused(); │ │458 + self.tagsView().selected = self.tagsViewActive(); │ │459 │ │460 // cap the list at list_max_width only while the detail pane fits beside│ │461 // it. the box drops the detail when the width can't hold both minimums,│ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────╮ │539 } │ │540 return; │ │541 } │ │481 - if (self.detailActive()) { │ │542 + if (self.tagsViewActive()) { │ │543 + self.tagsViewInput(key, root_focus); │ │544 + } else if (self.detailActive()) { │ │545 try self.detailInput(key, root_focus);│ │546 } else { │ │547 try self.listInput(key, root_focus); │ ╰───────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │548 } │ │549 } │ │550 │ │551 + // arrow keys move the tag selection; up from the top row crosses to the │ │552 + // sub header tabs. │ │553 + fn tagsViewInput(self: *View, key: Key, root_focus: *Focus) void { │ │554 + const tf = self.tagsView(); │ │555 + const cid = tf.focus.child_id orelse return; │ │556 + const cur = tf.indexOfFocusId(cid) orelse return; │ │557 + const count = tf.text_boxes.items.len; │ │558 + switch (key) { │ │559 + .arrow_left => if (cur > 0) root_focus.setFocus(tf.text_boxes.items[cur - 1].getFocus().id), │ │560 + .arrow_right => if (cur + 1 < count) root_focus.setFocus(tf.text_boxes.items[cur + 1].getFocus().id), │ │561 + .arrow_up => if (tf.rowStep(cur, false)) |i| root_focus.setFocus(tf.text_boxes.items[i].getFocus().id) else self.focusSubHeader(root_focus),│ │562 + .arrow_down => if (tf.rowStep(cur, true)) |i| root_focus.setFocus(tf.text_boxes.items[i].getFocus().id), │ │563 + .home => root_focus.setFocus(tf.text_boxes.items[0].getFocus().id), │ │564 + .end => root_focus.setFocus(tf.text_boxes.items[count - 1].getFocus().id), │ │565 + else => {}, │ │566 + } │ │567 + } │ │568 + │ │569 fn listInput(self: *View, key: Key, root_focus: *Focus) !void { │ │570 // up/down (and the scroll wheel) move the selection a row; page up/down │ │571 // jump a fixed amount. right/Enter cross into the detail pane. up from │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯