╭ Logout.zig ───────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const std = @import("std"); 2 const ui = @import("../../ui.zig"); 3 const inp = @import("../input.zig"); 4 const xit = @import("xit"); 5 const xitui = xit.xitui; 6 const wgt = xitui.widget; 7 const layout = xitui.layout; 8 const Key = xitui.input.Key; 9 const Grid = xitui.grid.Grid; 10 const Focus = xitui.focus.Focus; 11 12 const Self = @This(); 13 14 pub fn init() Self { 15 return .{}; 16 } 17 18 pub const View = struct { 19 center: ui.Center, 20 data: *const Self, 21 session: *ui.Session, 22 button_id: usize, 23 // focus id of the header's "users" tab; on logout we jump there so the 24 // user isn't stranded on a button that's about to be hidden. 25 users_tab_id: usize, 26 27 const prompt_index: usize = 0; 28 const button_index: usize = 1; 29 30 pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session, users_tab_id: usize) !View { 31 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .rounded_corners = true, .direction = .vert }); 32 errdefer box.deinit(allocator); 33 // marks this subtree as an HTML form scope for the web overlay 34 box.getFocus().kind = .{ .custom = "form:logout" }; 35 36 { 37 var prompt = try wgt.Text(ui.Widget).init(allocator, "are you sure?"); 38 errdefer prompt.deinit(allocator); 39 try box.children.put(allocator, prompt.getFocus().id, .{ 40 .widget = .{ .text = prompt }, 41 .rect = null, 42 .min_size = null, 43 }); 44 } 45 46 var button_id: usize = undefined; 47 { 48 var button = try wgt.TextBox(ui.Widget).init(allocator, "logout", .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); 49 errdefer button.deinit(allocator); 50 button.getFocus().focusable = true; 51 // the renderer distinguishes plain clickables from buttons that 52 // should POST to a server route by this kind. 53 button.getFocus().kind = .{ .custom = "submit" }; 54 button_id = button.getFocus().id; 55 try box.children.put(allocator, button.getFocus().id, .{ 56 .widget = .{ .text_box = button }, 57 .rect = null, 58 .min_size = null, 59 }); 60 } 61 62 box.getFocus().child_id = button_id; 63 64 return .{ 65 .center = try ui.Center.init(allocator, .{ .box = box }), 66 .data = data, 67 .session = session, 68 .button_id = button_id, 69 .users_tab_id = users_tab_id, 70 }; 71 } 72 73 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { 74 self.center.deinit(allocator); 75 } 76 77 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { 78 try self.center.build(allocator, constraint, root_focus); 79 } 80 81 pub fn input(self: *View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { 82 _ = allocator; 83 switch (key) { 84 .enter => { 85 try self.logout(root_focus); 86 return; 87 }, 88 .mouse => |mouse| { 89 if (inp.leftClickOn(root_focus, self.button_id, mouse)) { 90 try self.logout(root_focus); 91 return; 92 } 93 }, 94 else => {}, 95 } 96 } 97 98 fn logout(self: *View, root_focus: *Focus) !void { 99 self.session.data.user_id = null; 100 // jump focus back to the users tab — the logout button is about to 101 // be hidden by the tab-label swap. 102 root_focus.setFocus(self.users_tab_id); 103 } 104 105 pub fn clearGrid(self: *View) void { 106 self.center.clearGrid(); 107 } 108 109 pub fn getGrid(self: View) ?Grid { 110 return self.center.getGrid(); 111 } 112 113 pub fn getFocus(self: *View) *Focus { 114 return self.center.getFocus(); 115 } 116 117 pub fn getSelectedIndex(self: View) ?usize { 118 _ = self; 119 return 0; 120 } 121 }; 122