╭ 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.widget.Center, 20 data: *const Self, 21 session: *ui.Session, 22 button_id: usize, 23 24 const prompt_index: usize = 0; 25 const button_index: usize = 1; 26 27 pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session) !View { 28 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .round_corners = true, .direction = .vert }); 29 errdefer box.deinit(allocator); 30 // marks this subtree as an HTML form scope for the web renderer 31 box.getFocus().kind = .{ .custom = "form:logout" }; 32 33 { 34 var prompt = try wgt.Text.init(allocator, "are you sure?"); 35 errdefer prompt.deinit(allocator); 36 try box.children.put(allocator, prompt.getFocus().id, .{ 37 .widget = .{ .text = prompt }, 38 .rect = null, 39 .min_size = null, 40 }); 41 } 42 43 var button_id: usize = undefined; 44 { 45 var button = try wgt.TextBox.init(allocator, "logout", .{ .border_style = .single, .round_corners = true, .wrap_kind = .none }); 46 errdefer button.deinit(allocator); 47 button.getFocus().mode = .all; 48 // the renderer distinguishes plain clickables from buttons that 49 // should POST to a server route by this kind. 50 button.getFocus().kind = .{ .custom = "submit" }; 51 button_id = button.getFocus().id; 52 try box.children.put(allocator, button.getFocus().id, .{ 53 .widget = .{ .text_box = button }, 54 .rect = null, 55 .min_size = null, 56 }); 57 } 58 59 box.getFocus().child_id = button_id; 60 61 return .{ 62 .center = try ui.widget.Center.init(allocator, .{ .box = box }), 63 .data = data, 64 .session = session, 65 .button_id = button_id, 66 }; 67 } 68 69 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { 70 self.center.deinit(allocator); 71 } 72 73 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { 74 try self.center.build(allocator, constraint, root_focus); 75 } 76 77 pub fn input(self: *View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { 78 _ = allocator; 79 switch (key) { 80 .enter => { 81 try self.logout(); 82 return; 83 }, 84 .mouse => |mouse| { 85 if (inp.leftClickOn(root_focus, self.button_id, mouse)) { 86 try self.logout(); 87 return; 88 } 89 }, 90 else => {}, 91 } 92 } 93 94 fn logout(self: *View) !void { 95 self.session.logOut(); 96 // leave the auth tab for the page it belongs to, where the web's 97 // /logout redirect also lands 98 try self.session.navigate(self.session.data.current_page.pageRoot()); 99 } 100 101 pub fn clearGrid(self: *View) void { 102 self.center.clearGrid(); 103 } 104 105 pub fn getGrid(self: View) ?Grid { 106 return self.center.getGrid(); 107 } 108 109 pub fn getFocus(self: *View) *Focus { 110 return self.center.getFocus(); 111 } 112 113 pub fn atTop(self: View) bool { 114 _ = self; 115 return true; 116 } 117 }; 118