╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │348 aa: std.mem.Allocator, │ │349 commit_object: *xit.object.Object(repo_kind, repo_opts), │ │354 - limit: usize, │ │350 + full_message: bool, │ │351 ) !struct { []const u8, bool } { │ │352 var message: std.ArrayList(u8) = .empty; │ │357 - // a message past the limit keeps the bytes read so far │ │358 - const truncated = if (commit_object.readMessage(aa, &message, .limited(limit))) |_| │ │353 + const byte_truncated = if (commit_object.readMessage(aa, &message, .limited(max_message_size))) |_|│ │354 false │ │355 else |err| switch (err) { │ │356 error.StreamTooLong => true, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │357 else => |e| return e, │ │358 }; │ │364 - // the cut lands wherever the limit falls, so a truncated message keeps │ │365 - // only its whole lines: a line break can't fall inside a codepoint, and │ │366 - // the widgets need valid utf-8. a first line past the limit is instead │ │367 - // cut at the last codepoint boundary. │ │368 - const text = if (truncated) │ │369 - (if (std.mem.lastIndexOfScalar(u8, message.items, '\n')) |nl| message.items[0..nl] else trimIncompleteCodepoint(message.items))│ │359 + const preview_end = if (full_message) null else ui.detailPreviewEnd(message.items); │ │360 + const text = if (preview_end) |end| │ │361 + message.items[0..end] │ │362 + else if (byte_truncated) │ │363 + trimIncompleteCodepoint(message.items) │ │364 else │ │365 message.items; │ │372 - return .{ std.mem.trim(u8, text, " \t\r\n"), truncated }; │ │366 + return .{ std.mem.trim(u8, text, " \t\r\n"), byte_truncated or preview_end != null }; │ │367 } │ │368 │ │369 /// drop any incomplete UTF data from the end of a byte array │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────────╮ │src/ui/Repo/Discussions.zig│ ╰───────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │10 const thread = ui.widget.thread; │ │11 │ │12 const wasm = builtin.target.cpu.arch == .wasm32; │ │13 - │ │14 -// how much of a description the detail pane shows before linking to the│ │15 -// /description page, the same limit commit messages use. │ │16 -pub const max_description_size = 2 * 1024; │ │13 │ │14 // how many discussions one window shows before a "next" link appears. │ │15 pub const page_size = 20; │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │11 const thread = ui.widget.thread; │ │12 │ │13 const wasm = builtin.target.cpu.arch == .wasm32; │ │14 - │ │15 -// how much of a description the detail pane shows before linking to the│ │16 -// /description page, the same limit commit messages use. │ │17 -pub const max_description_size = 2 * 1024; │ │14 │ │15 // how many issues one window shows before a "next" link appears. │ │16 pub const page_size = 20; │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │15 const pch = @import("../../patch.zig"); │ │16 │ │17 const wasm = builtin.target.cpu.arch == .wasm32; │ │18 - │ │19 -// how much of a description the detail pane shows before linking to the│ │20 -// /description page, the same limit commit messages use. │ │21 -pub const max_description_size = 2 * 1024; │ │18 │ │19 // how many patches one window shows before a "next" link appears. │ │20 pub const page_size = 20; │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │640 } │ │641 │ │642 const whole = entry.record.event.description; │ │643 - const cut_short = !description_page and whole.len > Data.max_description_size; │ │644 - const shown = if (cut_short) │ │645 - std.mem.trimEnd(u8, whole[0 .. std.mem.lastIndexOfScalar(u8, whole[0..Data.max_description_size], '\n') orelse 0], " \t\r\n")│ │643 + const preview_end = if (description_page) null else ui.detailPreviewEnd(whole); │ │644 + const shown = if (preview_end) |end| │ │645 + std.mem.trimEnd(u8, whole[0..end], " \t\r\n") │ │646 else if (whole.len == 0) │ │647 "(no description)" │ │648 else │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │652 .rounded_corners = true, │ │653 .wrap_kind = .word, │ │654 .label = " description ", │ │655 - .bottom_label = if (cut_short) " click or press enter to see more " else "", │ │655 + .bottom_label = if (preview_end != null) " click or press enter to see more " else "",│ │656 }); │ │657 errdefer description.deinit(allocator); │ │658 description.getFocus().focusable = true; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │659 - if (cut_short) { │ │659 + if (preview_end != null) { │ │660 const route = ui.RoutablePage.repoThreadDescriptionRoute(kind, self.data.identity, entry.id) orelse return error.RouteTooLong; │ │661 description.getFocus().kind = .{ .custom = try std.fmt.allocPrint(self.session.page_arena.allocator(), "a:{s}", .{try route.toUrl(self.session.page_arena)}) };│ │662 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │675 try Comment.appendCount(allocator, inner_box, entry.comments.count, "comment", "comments"); │ │676 for (entry.comments.comments) |comment| try Comment.appendComment(allocator, inner_box, self.session, self.data.identity, kind, comment);│ │677 try Comment.appendWindowNav(allocator, inner_box, self.session, self.data.identity, kind, entry.id, null, entry.comments); │ │678 - │ │679 - var spacer = try Spacer.init(allocator); │ │680 - errdefer spacer.deinit(allocator); │ │681 - try inner_box.children.put(allocator, spacer.getFocus().id, .{ .widget = .{ .spacer = spacer }, .rect = null, .min_size = null }); │ │678 } │ │679 + } │ │680 + │ │681 + if (!description_page) { │ │682 + var spacer = try Spacer.init(allocator); │ │683 + errdefer spacer.deinit(allocator); │ │684 + try inner_box.children.put(allocator, spacer.getFocus().id, .{ .widget = .{ .spacer = spacer }, .rect = null, .min_size = null }); │ │685 } │ │686 │ │687 _ = self.focusFirst(null); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯