diff --git a/apps/weather/components/CityRail.css b/apps/weather/components/CityRail.css index 1b8daf5..0b2d569 100644 --- a/apps/weather/components/CityRail.css +++ b/apps/weather/components/CityRail.css @@ -31,7 +31,7 @@ gap: 4px; justify-content: flex-start; min-width: 0; - padding: 5px 6px 10px; + padding: 5px 6px; scroll-snap-align: start; } diff --git a/apps/weather/components/WeatherBackground.css b/apps/weather/components/WeatherBackground.css index 092ac6a..029336b 100644 --- a/apps/weather/components/WeatherBackground.css +++ b/apps/weather/components/WeatherBackground.css @@ -15,7 +15,11 @@ top: 0; width: 100%; height: 100%; - object-fit: contain; + /* The art is the 410x502 panel itself (the shell's exact aspect), so on that + shell cover and contain agree. On a taller viewport -- a resizable desktop + window -- cover fills it edge to edge instead of leaving solid bands above + and below the gradient. */ + object-fit: cover; } .weather-bg-img.is-hidden { diff --git a/apps/weather/components/WeatherBackground.tsx b/apps/weather/components/WeatherBackground.tsx index 39b4afb..4383258 100644 --- a/apps/weather/components/WeatherBackground.tsx +++ b/apps/weather/components/WeatherBackground.tsx @@ -5,22 +5,25 @@ import { weather } from '../stores/WeatherStore' // captured from the gea engine itself (WASM simulator), so they are pixel-identical // to the old CSS `.weather-shell` gradient — same radial glow, 158deg ramp, and // dither. The win: re-rasterizing this backdrop when content changes is a 1:1 -// decoded-image blit (the images are exactly panel-sized) instead of recomputing a -// 3-layer linear+radial gradient per pixel (~114ms, the bulk of a city switch). -// Inactive layers stay decoded (display:none) so switching visuals is instant — -// same pattern as WeatherVisual's hero art. Visual mapping is clear, cloud/fog, -// rain and snow; the root shell itself stays static. +// decoded-image blit (on the 410x502 panel the images are exactly panel-sized) +// instead of recomputing a 3-layer linear+radial gradient per pixel (~114ms, the +// bulk of a city switch). Inactive layers stay decoded (display:none) so switching +// visuals is instant — same pattern as WeatherVisual's hero art. Visual mapping is +// clear, cloud/fog, rain and snow; the root shell itself stays static. +// +// Fit comes from WeatherBackground.css, NOT a `fit` attribute: the attribute is an +// INLINE style, and inline styles replay after class rules, so it would override the +// taller-than-the-panel rule the phone/desktop targets need. export function WeatherBackground() { return (
- + - - + +
) } diff --git a/apps/weather/index.tsx b/apps/weather/index.tsx index 74c178f..7f0ac48 100644 --- a/apps/weather/index.tsx +++ b/apps/weather/index.tsx @@ -2,11 +2,13 @@ import { Display, mount } from '@geastack/core' import { App } from './components/App' import { weather } from './stores/WeatherStore' -// Weather needs WiFi for live forecasts. esp_wifi_init requires a chunk of -// internal DRAM (task stack + driver state) that the default 2-deep flush -// pipeline (~56 rows) leaves too little of — WiFi init fails ESP_ERR_NO_MEM and -// fetch() can never connect. A 36-row 2-deep pipeline frees ~32 KB internal so -// WiFi comes up; the smaller flush chunk is a fine trade for this app. +// ESP32-only tuning; both calls are inert setters on the phone and desktop +// targets (they just store the value, no panel to drive). Weather needs WiFi for +// live forecasts, and esp_wifi_init requires a chunk of internal DRAM (task stack +// + driver state) that the default 2-deep flush pipeline (~56 rows) leaves too +// little of — WiFi init fails ESP_ERR_NO_MEM and fetch() can never connect. A +// 36-row 2-deep pipeline frees ~32 KB internal so WiFi comes up; the smaller +// flush chunk is a fine trade for this app. Display.setBrightness(50) Display.setFlushConfig({ rows: 36, depth: 2 }) diff --git a/apps/weather/macos.json b/apps/weather/macos.json new file mode 100644 index 0000000..4a44534 --- /dev/null +++ b/apps/weather/macos.json @@ -0,0 +1,10 @@ +{ + "window": { + "title": "Weather", + "width": 546, + "height": 780, + "minWidth": 273, + "minHeight": 390, + "appearance": "dark" + } +} diff --git a/apps/weather/package.json b/apps/weather/package.json index 4b07ed4..ef4608f 100644 --- a/apps/weather/package.json +++ b/apps/weather/package.json @@ -22,11 +22,15 @@ "name": "Weather", "entry": "index.tsx", "runtime": "gea", + "designWidth": 273, "targets": { "web": true, "esp32": true, "geaos": false, - "android": true + "android": true, + "ios": true, + "macos": true, + "windows": true }, "icons": { "32": "icons/icon-32.png", diff --git a/apps/weather/stores/WeatherStore.ts b/apps/weather/stores/WeatherStore.ts index dbee455..020e45b 100644 --- a/apps/weather/stores/WeatherStore.ts +++ b/apps/weather/stores/WeatherStore.ts @@ -67,8 +67,14 @@ function hourLabel(hour: number): string { return '' + (hour - 12) + ' PM' } +// Carries the year, so a forecast that crosses New Year still sorts forward: +// without it January's key falls below December's and the hourly scan below +// runs off the end of the array, blanking every slot. function weatherTimeSortKey(time: string): number { - return Number(time.substring(5, 7)) * 744 + Number(time.substring(8, 10)) * 24 + Number(time.substring(11, 13)) + const year = Number(time.substring(0, 4)) + const month = Number(time.substring(5, 7)) + const day = Number(time.substring(8, 10)) + return ((year * 12 + month) * 31 + day) * 24 + Number(time.substring(11, 13)) } function weekdayFromISO(time: string): string { diff --git a/docs/EXAMPLE-CATALOG.md b/docs/EXAMPLE-CATALOG.md index 93fc6e2..55973ef 100644 --- a/docs/EXAMPLE-CATALOG.md +++ b/docs/EXAMPLE-CATALOG.md @@ -14,6 +14,7 @@ tests, and marketing proof. | Games | `sky-hop`, `sky-hop-jsx`, `tic-tac-toe`, `tilt-breakout`, `button-tetris` | Interaction, simple game loops, collision/physics, deterministic logic. | | Device features | `camera-showcase`, `camera-studio`, `voice-notes`, `hid-clicker`, `weather`, `maps` | Target capabilities such as camera, audio, HID, network, and map assets. | | Apple/native experiments | `notes-jsx`, `notes-native`, `ios-device-showcase`, `ios-metal-*`, `ios-native-showcase` | Apple target and native renderer experiments. | +| Cross-platform reference | `weather` | One source across embedded, phone and desktop: `esp32`, `android`, `ios`, `macos`, `web`. Scales its fixed-px layout through `gea.designWidth`. | | Windows/native experiments | `notes-jsx`, `notes-windows` | Windows target: the JSX notes app through the Win32 renderer, and the same app written against `@geastack/windows/Controls`. | | Reactive experiments | `reactive-counter`, `reactive-child-probe`, `reactive-nested-probe`, `reactive-tic-tac-toe` | Store/reactivity experiments, often hidden from launchers. |