╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Undo.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
607 if (self.data.clear) { 608 if (direction == .up) root_focus.setFocus(self.headerBox().getFocus().id) else try self.clearInput(key, root_focus); 609 return; 610 } 611 if (direction == .up and self.contentAtTop()) { 612 root_focus.setFocus(self.headerBox().getFocus().id); 613 return; 614 } 615 try self.refreshDetail(allocator); 616 if (self.detailActive()) { 617 const details = &self.detailScroll().child.box; 618 if (self.selected()) |index| { 619 if (activated(root_focus, details.children.keys()[0], key) and self.data.can_undo and self.data.items[index].index > 0) { 620 self.requestUndo(ui.RoutablePage.repoUndoRoute(self.data.identity, self.data.items[index].index) orelse return error.RouteTooLong); 621 return; 622 } 623 } 624 if (key == .arrow_left) root_focus.setFocus(self.listScroll().getFocus().id) else if (inp.rowDelta(key, @intCast(details.children.count()))) |delta| ui.widget.moveRowFocus(details, self.detailScroll(), root_focus, delta); 625 } else if (inp.rowDelta(key, @intCast(self.listScroll().child.box.children.count()))) |delta| { 626 ui.widget.moveRowFocus(&self.listScroll().child.box, self.listScroll(), root_focus, delta); 627 } else switch (key) { 628 .arrow_right, .enter => if (self.selected() != null) { 629 root_focus.setFocus(self.detailScroll().getFocus().id); 630 }, 631 else => {}, 632 } 633 } 634 635 // the confirm button submits the form the web renderer posts 636 fn clearInput(self: *View, key: Key, root_focus: *Focus) !void { 637 const center = &self.box.children.values()[content_index].widget.center; 638 const button_id = center.child.box.getFocus().child_id orelse return; 639 if (!activated(root_focus, button_id, key) or !self.data.can_undo) return; 640 self.requestUndo(ui.RoutablePage.repoUndoClearRoute(self.data.identity) orelse return error.RouteTooLong); 641 } 642 643 fn contentAtTop(self: *View) bool { 644 const scroll = if (self.detailActive()) self.detailScroll() else self.listScroll(); 645 const rows = &scroll.child.box; 646 const id = rows.getFocus().child_id orelse return true; 647 return rows.children.getIndex(id) == 0 and scroll.y == 0; 648 } 649 650 // moving up from the sub header returns to the page's tabs 651 pub fn atTop(self: *View) bool { 652 return self.headerActive(); 653 } 654 655 // arriving from the page's tabs lands on the sub header, not the content 656 pub fn focusHeader(self: *View, root_focus: *Focus) bool { 657 root_focus.setFocus(self.headerBox().getFocus().id); 658 return true; 659 } 660 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { 661 self.box.deinit(allocator); 662 } 663 pub fn clearGrid(self: *View) void { 664 self.box.clearGrid(); 665 } 666 pub fn getGrid(self: View) ?Grid { 667 return self.box.getGrid(); 668 } 669 pub fn getFocus(self: *View) *Focus { 670 return self.box.getFocus(); 671 } 672 }; 673