From fc5bb11152123e1aa6a95d177d9a361173f6ea70 Mon Sep 17 00:00:00 2001 From: jim kolpack Date: Sat, 10 Oct 2026 14:49:11 -0400 Subject: [PATCH] Center the 2x static time/temp line, and fix a length-check bug found along the way MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Centering itself was straightforward (Box + Row main_align="center"), but it silently wasn't firing: the length check gating the centered/ static presentation used a bare len(now["time_temp"]), and Starlark's len() on a string counts UTF-8 *bytes*, not characters. This string almost always has a multi-byte character (the middle-dot separator, the degree sign) -- confirmed len() reports 16 for a real 14-character string like "2:45 pm · 63°F", pushing it over the 15 threshold and silently routing it to the Marquee branch instead. Visually that looked like "the centering isn't working" (Marquee shows already-fitting content statically, left-aligned, instead of scrolling it) rather than an obvious bug. Fixed by counting via len(list(now["time_temp"].codepoints())) instead -- confirmed 14 for the same string. Verified centered to within 1px (4px left margin, 5px right, as close as integer pixels allow) once the length check was actually passing. --- subwave_nowplaying.star | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index 11df999..002a57e 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -233,8 +233,23 @@ def main(config): # 15 chars keeps a real margin against overflowing into the art # column instead of relying on a 1px coincidence. Always Marquee at # 1x, where the available width is tighter regardless of length. - time_temp_fits = scale == 2 and len(now["time_temp"]) <= 15 - time_temp_line = time_temp_text if time_temp_fits else render.Marquee(width = text_width, child = time_temp_text) + # + # Counted via codepoints, not a bare len(): Starlark's len() on a + # string counts UTF-8 *bytes*, and this string almost always has at + # least one multi-byte character (the \xb7 separator, \xb0 in the temp, + # if any) -- confirmed len() reports 16 for a real 14-character + # string here, which silently sent every normal-length string down + # the Marquee branch instead of the intended centered-static-text one + # (visually: text appeared "stuck" left-aligned with no error, since + # Marquee just shows already-fitting content statically rather than + # scrolling it -- easy to mistake for "the centering didn't work"). + time_temp_char_count = len(list(now["time_temp"].codepoints())) + time_temp_fits = scale == 2 and time_temp_char_count <= 15 + time_temp_line = ( + render.Box(width = text_width, child = render.Row(main_align = "center", expanded = True, children = [time_temp_text])) + if time_temp_fits else + render.Marquee(width = text_width, child = time_temp_text) + ) top_lines = [ render.Marquee(width = text_width, child = render.Text(now["title"], font = "tb-8", color = colors["text"])),