anthodev/lapin-futepublic Fork
⑂ develop
Commits
⬇ Clone ▾
git clone https://git.rickub.com/anthodev/lapin-fute.git
git clone ssh://git@rickub.com/anthodev/lapin-fute.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

[feature] Prefix metro and tram line labels on the watch display #24

Closed@github-anthodev opened this issue Sep 13, 2026
  • @github-anthodev opened this issue · Sep 13, 2026

    🔢 Impact Version (SemVer)

    PATCH


    📝 Description

    On the watch application, line badges render the raw catalog label. Metro favorites display as bare numbers (13) and tramways as (11), which reads ambiguously next to stop names and does not match how riders recognize IDFM lines. The companion should prepare the displayed label once per favorite: metro labels gain an M prefix and tramway labels a T prefix (13 → M13, 11 → T11). Metro "bis" lines get their suffix abbreviated (3bis, 3 bis, and already-prefixed M3bis all become M3b; 7bis becomes M7b). Every other mode — bus, RER, Transilien, and favorites without a mode — keeps its label byte-for-byte. The phone-side configuration page is not affected.


    📋 [Feature] Acceptance Criteria

    • prepareAppearance(favorite, profile, language) (packages/companion/src/display-layout.js:158) computes a local lineLabel from favorite.lineLabel right after source-string validation; its signature, exports, and existing validations (profile/language TypeError, empty-label checks, 448-byte record limit) are unchanged, and the favorite object is never mutated.
    • METRO: /^M?([0-9]+)\s*bis$/i matches are replaced with "M" + digits + "b"; other digit-leading labels gain M (13 → M13); already-prefixed (M13) and already-abbreviated (M3b) labels stay intact.
    • TRAM: digit-leading labels gain T (11 → T11); an already-prefixed T11 or a suffixed T3b stays intact; the bis contraction is never applied outside METRO.
    • All other cases preserve the exact string: BUS 13, RER A, Transilien L, a bus named 3bis, and favorites without lineMode.
    • The same derived lineLabel feeds the four line slots of the cut computation AND the serialized lp3 field inside content (hash input), so slot offsets and the serialized field can never diverge.
    • Watch rendering (packages/watch/src/embeddedjs/ui.js: chip, overview, departures, header) is unchanged; slots 0–3 render the prefixed label inside the existing useful widths (28/36/38 px). Measured with display-layout.measured(..., 1): M13 = 22 px, T11 = 20 px, T3a/T3b = 21 px, M3b/M7b = 23 px — all fit, including the 28 px compact Gabbro favorite, without ellipsis.
    • The traffic screen shares the line field and shows the same prefix, with no extra field and no new render branch.
    • Catalog, persisted favorites, colors, styles, and the D2 protocol are unchanged; the content hash changes naturally and the existing DIFF mechanism transmits the new record at the next synchronization, with no schema-version or generation bump.

    🔗 Affected Endpoints/Routes

    None — display-only text preparation, no API surface.

    File Role
    packages/companion/src/display-layout.js Producer: label derivation inside prepareAppearance (lines 158–184)
    packages/watch/src/embeddedjs/ui.js Unchanged consumers used for verification (overview slots 0/1, departures slot 2, header slot 3)
    packages/watch/test/packed.test.js Interoperable regression with the real producer

    🧪 Tests to Add

    Type Coverage
    Watch packed regression (node --test packages/watch/test/packed.test.js) Real prepareAppearance + appearanceValid/field/clipped from watchModule("packed"), profiles 0 and 1: METRO 13 → M13, TRAM 11 → T11, pre-prefixed T11 → T11; preservation of M13, T3b, BUS 13, RER A, Transilien L, and a modeless favorite; bis cases 3bis/7bis/3 bis/M3bis/M3b; BUS 3bis stays 3bis; record validity; favorite immutability
    Full suite npm test stays green
    Radio gate npm run measure:radio budgets unchanged (768/192-byte dictionaries, 15-dictionary FULL config, 18+2 startup attempts, 15025 exclusion)
    Renderer smoke (temporary, under var/) renderHarness-based navigation on both profiles: list and detail views show M13/T11 and M3b/M7b, compact Gabbro favorite without ellipsis

    ⚙️ Constraints

    • Frozen wire contract: no message IDs, budgets, targets, schema versions, or generation semantics change; the trilateral alias-map pin stays untouched.
    • No watch-side code changes, no badge size or font changes, no catalog or favorites mutation, no new exported helpers, no secret-boundary impact.
    • Node 24.18.0 pinned; Bun and the pebble CLI are user-managed (missing tools must exit 127, never auto-install).

    🔀 [Conditional] Dependencies

    None.


    ⚠️ [Conditional] Impact on Existing Behavior

    • Watch labels for METRO/TRAM favorites change on the first synchronization after the update; the existing DIFF mechanism delivers the new records through the natural content-hash change.
    • The traffic detail header shows the prefixed label because it shares the line field.
    • The configuration page and the static catalog display remain unchanged.

    🔍 [Conditional] Technical Context

    • Sole producer caller: packages/companion/src/index.js:381 (layout.prepareAppearance(favorite, binding.profile, language)).
    • Shared field consumers: packages/watch/src/embeddedjs/ui.js:44 (chip), fed by overview, departures, and header.
    • Native rendering is not certified by host suites; final visual proof requires an isolated emulator run and is out of scope for this ticket's host gates.

Sign in to comment.