╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Events.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │634 return; │ │635 } │ │636 switch (key) { │ │636 - .enter => if (self.syncFocused()) self.requestSync(), │ │637 - .mouse => |mouse| if (self.button_id) |id| if (inp.leftClickOn(root_focus, id, mouse)) self.requestSync(), │ │637 + .enter => if (self.syncFocused()) try self.requestSync(allocator), │ │638 + .mouse => |mouse| if (self.button_id) |id| if (inp.leftClickOn(root_focus, id, mouse)) try self.requestSync(allocator),│ │639 else => {}, │ │640 } │ │640 - _ = allocator; │ │641 } │ │642 │ │643 - fn requestSync(self: *Header.View) void { │ │643 + fn requestSync(self: *Header.View, allocator: std.mem.Allocator) !void { │ │644 if (!self.session.is_terminal) return; │ │645 if (self.session.host_request != null) return; │ │646 - self.session.host_request = .sync_events; │ │646 const button_id = self.button_id orelse return; │ │647 const child = self.box.children.getPtr(button_id) orelse return; │ │648 const button = switch (child.widget) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │649 .text_box => |*button| button, │ │650 else => return, │ │651 }; │ │653 - button.content = "syncing..."; │ │654 - for (button.box.children.values()) |*line| switch (line.widget) {│ │655 - .text => |*text| text.content = "syncing...", │ │656 - else => {}, │ │657 - }; │ │652 + try button.setContent(allocator, "syncing..."); │ │653 + self.session.host_request = .sync_events; │ │654 } │ │655 │ │656 fn syncFocused(self: *Header.View) bool { │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │253 var list_box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .vert, .stretch = true });│ │254 errdefer list_box.deinit(allocator); │ │255 │ │256 - // labels and link kinds are borrowed by the rows, so they live in │ │257 - // the page arena (as long as this page's widget tree). │ │256 + // link kinds are borrowed by the rows, so they live in the page │ │257 + // arena (as long as this page's widget tree). row labels are │ │258 + // copied by their text boxes. │ │259 const aa = session.page_arena.allocator(); │ │260 if (data.dir.len != 0) { │ │261 try addRow(allocator, &list_box, "..", try dirLink(session.page_arena, data, parentDir(data.dir))); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │358 │ │359 // the selected file's contents as a single focusable multi-line text box. │ │360 // it's borderless — the border lives on the surrounding scroll frame, which │ │360 - // doubles when this content is focused. `text` lives in the page arena. a │ │361 - // non-empty `link` makes activating the box follow it, like addRow. │ │361 + // doubles when this content is focused. a non-empty `link` makes activating │ │362 + // the box follow it, like addRow. │ │363 fn addContentBox(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), text: []const u8, link: []const u8) !void {│ │364 _ = self; │ │365 var tb = try wgt.TextBox(ui.Widget).init(allocator, text, .{ .border_style = null, .wrap_kind = .none }); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭──────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 +const evt = @import("../../event.zig");│ │3 const ui = @import("../../ui.zig"); │ │4 const inp = @import("../input.zig"); │ │5 const xit = @import("xit"); │ ╰──────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │73 │ │74 // the user's name (local mode has no user pages to link to) │ │75 if (!session.data.is_local) { │ │75 - const text = try std.fmt.allocPrint(aa, "{s}/", .{data.owner_name}); │ │76 + var text_buf: [evt.User.name_max_len + 1]u8 = undefined; │ │77 + const text = try std.fmt.bufPrint(&text_buf, "{s}/", .{data.owner_name}); │ │78 const link = try std.fmt.allocPrint(aa, "a:/user/{s}", .{data.owner_name}); │ │79 │ │80 var text_box = try wgt.TextBox(ui.Widget).init(allocator, text, .{ .border_style = .hidden, .wrap_kind = .none });│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │587 for ([_]evt.Issue.Status{ .open, .closed }) |status| { │ │588 const route = ui.RoutablePage.repoIssuesRoute(data.identity, status, data.tag, "") orelse return error.RouteTooLong;│ │589 const link = try std.fmt.allocPrint(aa, "ai:{s}", .{try route.toUrl(session.page_arena)}); │ │590 - const label = try std.fmt.allocPrint(aa, "{s} ({d})", .{ @tagName(status), data.window(status).count }); │ │590 + var label_buf: [64]u8 = undefined; │ │591 + const label = try std.fmt.bufPrint(&label_buf, "{s} ({d})", .{ @tagName(status), data.window(status).count }); │ │592 try addTab(allocator, &box, &tab_ids, label, link); │ │593 } │ │594 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │629 if (data.conflicts.count > 0) { │ │630 const route = ui.RoutablePage.repoIssuesConflictsRoute(data.identity, "") orelse return error.RouteTooLong;│ │631 const link = try std.fmt.allocPrint(aa, "ai:{s}", .{try route.toUrl(session.page_arena)}); │ │631 - const label = try std.fmt.allocPrint(aa, "conflicts ({d})", .{data.conflicts.count}); │ │632 + var label_buf: [64]u8 = undefined; │ │633 + const label = try std.fmt.bufPrint(&label_buf, "conflicts ({d})", .{data.conflicts.count}); │ │634 try addTab(allocator, &box, &tab_ids, label, link); │ │635 } │ │636 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Threads.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │242 const route = removeRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong;│ │243 const action = try std.fmt.allocPrint(aa, "form:{s}", .{try route.toUrl(session.page_arena)}); │ │244 const event_name = if (data.comment_id.len == 0) thread_name else "comment"; │ │245 - const label = try std.fmt.allocPrint(aa, "remove {s}", .{event_name}); │ │245 + var label_buf: ["remove ".len + @max(thread_name.len, "comment".len)]u8 = undefined; │ │246 + const label = try std.fmt.bufPrint(&label_buf, "remove {s}", .{event_name}); │ │247 var center = try initRemoveForm(allocator, action, label); │ │248 errdefer center.deinit(allocator); │ │249 try stack.children.put(allocator, center.getFocus().id, .{ .center = center }); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1118 } │ │1119 │ │1120 if (comment_page) |page| { │ │1120 - const back_label = try std.fmt.allocPrint(self.session.page_arena.allocator(), "← back to {s}", .{thread_name}); │ │1121 + var back_label_buf: ["← back to ".len + thread_name.len]u8 = undefined; │ │1122 + const back_label = try std.fmt.bufPrint(&back_label_buf, "← back to {s}", .{thread_name}); │ │1123 var back = try Comment.linkBox(allocator, self.session, back_label, commentsRoute(self.data.identity, entry.id, 0) orelse return error.RouteTooLong);│ │1124 errdefer back.deinit(allocator); │ │1125 try inner.children.put(allocator, back.getFocus().id, .{ .widget = .{ .text_box = back }, .rect = null, .min_size = null }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯