╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1994 var box = try wgt.Box(Widget).init(allocator, .{ .border_style = null, .direction = .vert }); │ │1995 errdefer box.deinit(allocator); │ │1996 const bg_id = bg_blk: { │ │1992 - var background = try AnsiBackground.init(allocator, page_widget, demon_art, session); │ │1997 + var background = try AnsiBackground.init(allocator, page_widget, session); │ │1998 errdefer background.deinit(allocator); │ │1999 const id = background.getFocus().id; │ │2000 try box.children.put(allocator, id, .{ .widget = .{ .background = background }, .rect = null, .min_size = null });│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2007 } │ │2008 box.getFocus().child_id = bg_id; │ │2009 break :blk Widget{ .box = box }; │ │2005 - } else Widget{ .background = try AnsiBackground.init(allocator, page_widget, demon_art, session) };│ │2010 + } else Widget{ .background = try AnsiBackground.init(allocator, page_widget, session) }; │ │2011 errdefer root.deinit(allocator); │ │2012 │ │2013 // input-owning views build their TextInputs in init — so reset the │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │2023 return root; │ │2024 } │ │2025 │ │2026 +// native and server-side sessions choose from the embedded collection. WASM│ │2027 +// keeps the art serialized by the server instead. │ │2028 +fn chooseAnsiArtForNavigation(session: *Session) void { │ │2029 + if (comptime ansi_arts.len == 0) return; │ │2030 + const io = session.io orelse return; │ │2031 + var random: usize = undefined; │ │2032 + io.random(std.mem.asBytes(&random)); │ │2033 + session.data.ansi_art = ansi_arts[random % ansi_arts.len]; │ │2034 +} │ │2035 + │ │2036 pub const Widget = union(enum) { │ │2037 text: wgt.Text(Widget), │ │2038 box: wgt.Box(Widget), │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2963 const len = std.unicode.utf8ByteSequenceLength(byte) catch 1; │ │2964 const end = @min(content.len, i + len); │ │2965 const rune = content[i..end]; │ │2951 - const transparent = end - i == 1 and rune[0] == ' ' and │ │2952 - style.fg == null and style.bg == null and !style.inverted; │ │2966 + // a foreground color does not make a space visible. only an │ │2967 + // effective background makes it opaque; foreground state often │ │2968 + // remains active through the padding at the end of a row. │ │2969 + const effective_background = if (style.inverted) style.fg else style.bg; │ │2970 + const transparent = end - i == 1 and rune[0] == ' ' and effective_background == null;│ │2971 try row.append(allocator, .{ │ │2972 .rune = if (transparent) null else rune, │ │2973 .style = style, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │3063 art: AnsiArt, │ │3064 session: *Session, │ │3065 │ │3048 - pub fn init(allocator: std.mem.Allocator, child_widget: Widget, art_content: []const u8, session: *Session) !AnsiBackground {│ │3066 + pub fn init(allocator: std.mem.Allocator, child_widget: Widget, session: *Session) !AnsiBackground { │ │3067 var cw = child_widget; │ │3068 const child = allocator.create(Widget) catch |e| { │ │3069 cw.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │3074 child.deinit(allocator); │ │3075 allocator.destroy(child); │ │3076 } │ │3059 - return .{ .grid = null, .child = child, .art = try AnsiArt.init(allocator, art_content), .session = session }; │ │3077 + return .{ .grid = null, .child = child, .art = try AnsiArt.init(allocator, session.data.ansi_art), .session = session };│ │3078 } │ │3079 │ │3080 pub fn deinit(self: *AnsiBackground, allocator: std.mem.Allocator) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │3097 }, root_focus); │ │3098 │ │3099 if (self.session.data.enable_ansi) { │ │3100 + self.art.content = self.session.data.ansi_art; │ │3101 if (self.child.getGrid()) |fg| { │ │3102 self.grid = try artBehind(allocator, fg, &self.art, .top_right, self.session.is_terminal, root_focus);│ │3103 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │3139 │ │3140 // the art is dimmed to this fraction of its brightness so foreground text│ │3141 // stays legible over it │ │3123 - const art_brightness = 45; // percent │ │3142 + const art_brightness = 35; // percent │ │3143 │ │3144 fn dimColor(color: ?Grid.Color) ?Grid.Color { │ │3145 const c = color orelse return null; │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │1488 }; │ │1489 session.io = io; │ │1490 │ │1491 - const snapshot: ui.Snapshot = .{ │ │1492 - .page = try ui.Page.init(session.page_arena, &session, session.data.current_page),│ │1493 - .session = session.data, │ │1494 - }; │ │1495 - var root = try ui.initRoot(allocator, &snapshot.page, &session); │ │1491 + var page = try ui.Page.init(session.page_arena, &session, session.data.current_page); │ │1492 + var root = try ui.initRoot(allocator, &page, &session); │ │1493 defer root.deinit(allocator); │ │1494 + │ │1495 + const snapshot: ui.Snapshot = .{ .page = page, .session = session.data }; │ │1496 │ │1497 const content = try generateHtml(allocator, &root); │ │1498 defer allocator.free(content); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯