From d92609e04645b6f229453946cca3ef3fd1a067ce Mon Sep 17 00:00:00 2001 From: codex-bot Date: Sat, 12 Sep 2026 13:11:24 +0100 Subject: [PATCH] Salah 0.4: center-magnified prayer times and larger clock --- README.md | 25 ++++++++++++++---------- preview-0.4.png | Bin 0 -> 17481 bytes src/manifest.json | 4 ++-- src/pages/index/index.ux | 40 +++++++++++++++++++++++++++------------ tests/focus.cjs | 40 +++++++++++++++++++++++++++++++++++++++ tests/page.cjs | 2 ++ 6 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 preview-0.4.png create mode 100644 tests/focus.cjs diff --git a/README.md b/README.md index e7cf29e..c2db146 100644 --- a/README.md +++ b/README.md @@ -19,18 +19,22 @@ Morocco (Ministry of Habous), matching AlAdhan `method=21`: All computation happens **on the watch** — no GPS, no network. Pure solar math (same Meeus approach as the sundial) lives in `src/common/prayer.js`. -## Screen (v0.3) +## Screen (v0.4) -- Pure #000000 AMOLED background, including the list and prayer rows -- Larger 42px clock, 28px prayer names and 36px times -- Native vertically swipe-scrollable list: 80px rows in a 320×240px viewport -- Top/bottom spacers let the first and last prayers scroll to the center -- Fixed next-prayer countdown; lavender outline/text highlight the next prayer -- Normal system back button exits; no crown support assumed -- 15s refresh; no changes to prayer calculations +- Pure #000000 AMOLED background +- Larger 50px clock; no swipe instruction label +- Prayer names above their times, in fixed 104px native list rows +- Center magnification: prayer times grow continuously from 30px to 60px as + their row approaches the physical screen center; names grow from 20px to 28px +- Scroll viewport 320×264 at x73/y101, centered at y233; 80px end spacers +- Fixed next-prayer countdown below the list; lavender next-prayer highlight +- Glyph sizes change without changing row heights, avoiding scroll-position drift +- 15s clock refresh preserves scroll focus; calculation logic unchanged +- Normal system back exits; crown support not assumed -Build and automated tests pass; v0.3 scrolling/rendering needs an on-watch check. -`preview-0.3.png` is a static layout mock with illustrative times, not a watch screenshot. +Automated math/page/focus/layout tests and release build pass. The live scroll +magnification still needs an on-watch check. `preview-0.4.png` is a static layout +mock with illustrative times, not a device screenshot. ## Project layout @@ -56,6 +60,7 @@ npm run release node tests/prayer.cjs node tests/page.cjs node tests/amoled.cjs +node tests/focus.cjs ``` ## Install diff --git a/preview-0.4.png b/preview-0.4.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf2a3ab17e21036dc054a52116a69e7aeeffb9f GIT binary patch literal 17481 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 nextName }} in {{ countdown }} - +
- {{ row.label }} - {{ row.time }} + {{ row.label }} + {{ row.time }}
- SWIPE TO SCROLL diff --git a/tests/focus.cjs b/tests/focus.cjs new file mode 100644 index 0000000..f59a911 --- /dev/null +++ b/tests/focus.cjs @@ -0,0 +1,40 @@ +const assert = require('node:assert/strict') +const fs = require('node:fs') +const vm = require('node:vm') +const src = fs.readFileSync('src/pages/index/index.ux', 'utf8') +const body = src.match(/