From 832ff25c41717ffe62e1404cb097d83ca68385c6 Mon Sep 17 00:00:00 2001 From: Marc-Oliver Ochlast Date: Thu, 11 Jun 2026 12:40:41 +0200 Subject: [PATCH 1/2] Fix weather icons not rendering on device (#23) The device render path (renderDesignAsHtml -> Puppeteer -> generateWeatherContent) embedded the raw SVG primitives returned by getWeatherIconSvg() directly into an HTML
, without an enclosing element. Browsers only render SVG primitives inside an , so the weather icon was invisible on the device while still showing in the frontend designer preview (which uses a proper wrapper). Wrap the icon markup in a sized element (matching the existing battery/wifi widget pattern) and add font-family to the snow glyphs for robust text rendering. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../screen-designer/services/screen-renderer.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/screen-designer/services/screen-renderer.service.ts b/backend/src/screen-designer/services/screen-renderer.service.ts index ff95939..18bec68 100644 --- a/backend/src/screen-designer/services/screen-renderer.service.ts +++ b/backend/src/screen-designer/services/screen-renderer.service.ts @@ -776,9 +776,9 @@ export class ScreenRendererService implements OnModuleDestroy, OnModuleInit { - * - * - * + * + * + * `; case 'thunder': return ` @@ -2961,7 +2961,7 @@ export class ScreenRendererService implements OnModuleDestroy, OnModuleInit { html += '
'; if (showIcon) { - html += `
${this.getWeatherIconSvg(condition.icon, iconSize, 'currentColor')}
`; + html += `${this.getWeatherIconSvg(condition.icon, iconSize, 'currentColor')}`; } html += '
'; if (showTemperature) { From f2e232cdb7f39034c48973078dd37b3403e9e812 Mon Sep 17 00:00:00 2001 From: Marc-Oliver Ochlast Date: Thu, 11 Jun 2026 13:37:10 +0200 Subject: [PATCH 2/2] Render emoji as monochrome glyphs so they survive e-ink dithering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Color emoji (e.g. ⚡ rendered via fonts-noto-color-emoji) turn bright in the grayscale + Floyd-Steinberg pass and end up above the white threshold, so they vanish on the device while showing in the browser preview. Swap the color emoji font for the monochrome Symbola font and list it as a per-glyph fallback in mapFontFamily, so emoji render as black glyphs that survive dithering. No widget content changes needed. Co-Authored-By: Claude Opus 4.8 (1M context) --- Dockerfile | 2 +- .../services/screen-renderer.service.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index a931468..b3d6cc9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -91,7 +91,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ nginx \ # Chrome headless shell dependencies wget ca-certificates openssl unzip \ - fonts-liberation fonts-noto-color-emoji fonts-noto-cjk fontconfig \ + fonts-liberation fonts-symbola fonts-noto-cjk fontconfig \ libnss3 libatk-bridge2.0-0t64 libdrm2 libxkbcommon0 \ libgbm1 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \ libasound2t64 libcups2t64 libatk1.0-0t64 libnspr4 libdbus-1-3 \ diff --git a/backend/src/screen-designer/services/screen-renderer.service.ts b/backend/src/screen-designer/services/screen-renderer.service.ts index 18bec68..7e7e53f 100644 --- a/backend/src/screen-designer/services/screen-renderer.service.ts +++ b/backend/src/screen-designer/services/screen-renderer.service.ts @@ -149,16 +149,19 @@ export class ScreenRendererService implements OnModuleDestroy, OnModuleInit { * This ensures the loaded woff2 fonts are actually used */ private mapFontFamily(fontFamily: string): string { + // 'Symbola' is a monochrome symbol/emoji font (installed in the image). It is + // listed as a per-glyph fallback so emoji render as black glyphs that survive + // the grayscale + Floyd-Steinberg dithering for e-ink (color emoji turn white). switch (fontFamily) { case 'sans-serif': - return "'Inter', sans-serif"; + return "'Inter', 'Symbola', sans-serif"; case 'monospace': - return "'Roboto Mono', monospace"; + return "'Roboto Mono', 'Symbola', monospace"; case 'serif': - return "'Merriweather', serif"; + return "'Merriweather', 'Symbola', serif"; default: // If already a specific font or unknown, return with fallback - return fontFamily.includes(',') ? fontFamily : `${fontFamily}, sans-serif`; + return fontFamily.includes(',') ? fontFamily : `${fontFamily}, 'Symbola', sans-serif`; } }