feat(kiosk): point donors to the card reader with a per-tablet NFC hint - #6
Merged
osayed0001 merged 1 commit intoAug 9, 2026
Merged
Conversation
During the card step the kiosk can now show a pulsing contactless (NFC) symbol with arrows marching toward it, on the side where the reader is mounted, turning green when the payment clears. - New per-device setting `nfcSide` (off/left/right), set in Admin → Devices → "Reader side". Default 'off' — existing kiosks unchanged. Wired end to end exactly like the existing per-device `orientation`: server device column + setter + zod route + per-device injection into getKioskConfig; web api.ts + devices.tsx control; Android KioskConfig + DataStore + JSON parse. - New NfcReaderHint composable (Compose Canvas): contactless waves + a marching-chevron arrow group, aligned to the logical left/right edge. It lives inside RotatedRoot, so left/right follow the mount and become top/bottom on a portrait tablet. Pulses on Card/Processing; SuccessDark green with arrows fading on Thanks (cleared). Adds a store test covering nfcSide sanitisation + per-device delivery.
hasan-ismail
added a commit
that referenced
this pull request
Aug 9, 2026
…#6 build PR #6 (the per-tablet NFC reader hint) failed :app:compileReleaseKotlin with 8 errors, so the APK job failed and the image job was SKIPPED — nothing published, and dev stayed on dev.6. All 8 errors are one missing import. `animateFloat` is an EXTENSION on InfiniteTransition (androidx.compose.animation.core, file class InfiniteTransitionKt), so Kotlin needs it imported by name. The file imported `animateFloatAsState` — a different, top-level function — which is why line 127 compiled while lines 82 and 121 did not. Easy to miss because this is the first rememberInfiniteTransition in the codebase, so there was no import block to copy. The other 6 errors were cascade, which is why the log looked worse than the bug: 82/121 Unresolved reference 'animateFloat' 85/124 Cannot infer type → the animationSpec lambda, from the failed call 145 Overload resolution ambiguity → `phase` had an error type, so sin() couldn't choose between sin(Double) and sin(Float) 147 Double where Float expected → `wave`/`a` fell out of the Double branch above All of them resolve once `phase` and `pulse` are State<Float> again. Verified rather than assumed, since Android can't be compiled on this machine: pulled animation-core-android-1.7.3 (resolved from composeBom 2024.09.03) from Google Maven and read the signature out of the artifact — public static final State<Float> animateFloat(InfiniteTransition, float initialValue, float targetValue, InfiniteRepeatableSpec<Float> animationSpec, String label, ...) — which matches both call sites exactly, and confirmed every other symbol the new file touches resolves (SuccessDark, RotatedRoot, GivingStep.Card/Processing/Thanks, and the BoxScope receiver at the GivingHome call site, which sits in the same Box that does .align(Alignment.TopEnd) below it). Also checked the half of PR #6 that CI never reached, because a skipped image job means the server and web changes were merged with ZERO validation: server tsc clean, 120/120 tests pass (its nfcSide assertions included), web tsc + build clean, nfcSide traced end to end (store → kiosk config → Models → DeviceStore → KioskApi → GivingHome). This PR was clean where the last two were not — no main merge, compose line correct, CHANGELOG prepended without destroying history. Bumped to 0.11.0-dev.7 so the NFC hint is actually installable; dev.6 never carried it.
hasan-ismail
added a commit
that referenced
this pull request
Aug 10, 2026
… be installed PR #7 built green, but green is not the same as shipped. It changed only NfcHint.kt and left every version field alone, so the build republished the SAME tag, :0.11.0-dev.7, with different content. Two consequences, both silent: 1. NOBODY CAN GET IT. OpenMasjidOS decides an app has an update by comparing the catalog's `version:` with the installed one. The catalog still said 0.11.0-dev.7 because the manifest still said 0.11.0-dev.7, so a box already on dev.7 sees no change, is never notified, and has nothing to install. This is exactly the failure mode CLAUDE.md rule 6b exists to prevent — a dev build that reuses a version is undetectable. 2. THE TAG MUTATED. The dev channel's whole integrity story is that :X.Y.Z-dev.N is an exact, immutable tag (that is what lets the compose pin a bare tag instead of a digest). Verified it moved: :0.11.0-dev.7 after PR #6's fix sha256:82f00a87d0ead9a03b0cb261064f09bfe81d9ed… :0.11.0-dev.7 now sha256:d609a187272f20e84569a9ed95993ff1073f6f48… So "dev.7" now names two different builds depending on when you pulled. A box that installed the first one reports dev.7 and is right; the registry says dev.7 and is also right; they are different software. Worth knowing if anything odd shows up on a box that updated in that window. The CI channel guard can't catch this: it checks the compose tag MATCHES manifest, and both were consistently dev.7. Consistent-but-stale passes. Nothing in the pipeline compares the version against what dev last published, which is why this needs a human or a habit rather than a check. Cheapest fix is the habit in rule 6b: the version bump belongs in the same push as the change it ships. dev.8 is content-identical to the mutated dev.7 plus the version fields, so this is purely about making PR #7 reachable. No changelog entry: the Unreleased section already describes the NFC hint, and this is a size tweak to a feature that has never shipped. Verified: server tsc clean, 120/120 tests, web tsc + build clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
During the card step the kiosk can now show a pulsing contactless (NFC) symbol with arrows marching toward it, on the side where the reader is mounted, turning green when the payment clears.
nfcSide(off/left/right), set in Admin → Devices → "Reader side". Default 'off' — existing kiosks unchanged. Wired end to end exactly like the existing per-deviceorientation: server device column + setter + zod route + per-device injection into getKioskConfig; web api.ts + devices.tsx control; Android KioskConfig + DataStore + JSON parse.Adds a store test covering nfcSide sanitisation + per-device delivery.