|
2 | 2 |
|
3 | 3 | ## Added |
4 | 4 |
|
| 5 | +- **Debug-only reader readout in the TigerPOD modal** (admin/debug mode) — in place of the removed ownership toggle, it shows what the app currently treats as an **active** reader (name + whether a chip is on it), plus the account's TigerPOD telemetry (lifetime max reader count, `hasPod`). Reads live state (`state.nfcReaders`, `state.nfcCardPresent`, `_telRfidMax`) and **refreshes in real time** — the reader plug/unplug and card present/removed handlers re-render it while the modal is open (guarded so it's a no-op when closed), and it also repaints when the telemetry read lands — `hydratePodSignal` is a fire-and-forget read at connect, so a modal opened before it returned showed the pre-hydration defaults (max 0, hasPod false) until now. Shows current vs max reader count side by side. Hidden entirely for non-debug users. Admin/dev surface — not user-facing — `renderer/inventory.js`, `renderer/inventory.html`, `renderer/css/60-modals.css` |
| 6 | + |
| 7 | +- **Reader-selection panel brief** — `docs/READER-SELECTION-BRIEF.md`, the frozen spec for a per-reader active/inactive panel: the set of active readers is what the app considers usable (burn flow, card-present, "no reader" prompt all key off it). Smart defaults fold the YubiKey filter in (security keys default off with the reason shown, real readers default active), choices persist per reader, and it handles the two-identical-ACR122U case. Ships the immediate YubiKey fix now; the panel is the general control — `docs/READER-SELECTION-BRIEF.md` |
| 8 | + |
5 | 9 | - **`.ttag` export/import brief** — `docs/TTAG-EXPORT-BRIEF.md`, the frozen spec for backing up inventory materials to a `.ttag` file so they live outside the cloud. A `.ttag` is a verbatim copy of the Firestore doc(s), `records[]` of 1→N (one spool / a twin / the whole inventory, no branching); twins are atomic (exporting one always exports both) and re-paired from `twin_tag_uid` in the data; import validates then previews then accepts, with restore (same account, verbatim) vs import (other account, ids regenerated + twin refs remapped) modes. Frozen identifiers (`.ttag`, UTI `io.tigertag.ttag`, ProgID `TigerTag.ttag`, content marker), and a Phase 1 (export + file-picker import, testable in dev) / Phase 2 (OS association, needs a build) / Phase 3 (whole-inventory) split. The signed TigerTag+ backup (a separate `rfidList` collection, not the inventory doc) rides along in a required `rfidBackups` map so the backup is complete. A multi-material export asks grouped (one file, all records) vs individual (one file per material); a twin is 2 records but one material, so it stays one file and counts as individual — `docs/TTAG-EXPORT-BRIEF.md` |
6 | 10 |
|
7 | 11 | - **Length-limited fields now shake when they reject a keystroke** — a `maxlength` field used to swallow the over-the-limit character in silence; on desktop the equivalent of a phone's haptic "no" is a quick horizontal shake, so the rejection is seen. One delegated `beforeinput` listener covers **every** `[maxlength]` input and textarea in the app (13 today, from the 3-char friend-code boxes to the 500-char list message), present or added later, so nothing is wired per field. It fires only on a genuinely rejected insert — a paste or keystroke that would overflow, accounting for any selected text it would replace. Honours `prefers-reduced-motion`: a single danger-tinted border flash instead of movement. Shared `bumpField()` helper + `fieldBump` keyframe, reusable for any future hard-limit feedback — `renderer/inventory.js`, `renderer/css/00-base.css` |
|
10 | 14 |
|
11 | 15 | ## Changed |
12 | 16 |
|
| 17 | +- **The stock-value tile shows its HT/TTC qualifier next to the price, not under the label** — `236.60 € excl. tax` instead of `236.60 €` with `STOCK VALUE · excl. tax` below. It qualifies the figure, so it belongs on the figure's line. The number is wrapped in its own span so the count-up tween (which sets `.value` textContent) no longer wipes the suffix; the qualifier has its own muted colour so the up/down tint never turns it green/red — `renderer/inventory.js`, `renderer/css/00-base.css` |
| 18 | + |
13 | 19 | - **New chipless spools are minted with a `TigerData_` id prefix** (was `CLOUD_`), so an exported `.ttag` never shows a confusing `CLOUD_` id — the file carries the tier name the user knows. The prefix is a *discriminator*, not a display value: `isCloud = spoolId.startsWith("CLOUD_")` decided the whole chipless path. Rather than migrate (a Firestore doc-id rename is delete+recreate across every account) the discriminator now accepts **both** prefixes via a shared `_isChiplessId` — `CLOUD_` stays recognised forever for the docs already out there, `TigerData_` is used going forward. Studio has a single discriminator point (`normalizeRow`) and a single mint point (`_adpCloudId`), both updated. The filter chain is unchanged: `TigerData_` → `isCloud` → `protocol:"TigerCloud"` → shown as "TigerData", so it lands under the existing search selector. **This prefix is read by four codebases** — the same both-prefixes generalisation was applied to the mobile app (`main_inventory.dart`), the Hub (`lib/data/inventory.ts`) and the stats Cloud Function (`functions/index.js`, where `cloudCount` would otherwise under-count), plus the `llms.txt` / backend-README docs. **Deployment order matters**: a `TigerData_` spool created in Studio syncs to Firestore and is read by the phone / Hub / Function immediately, so their both-prefix updates must be live before the Studio release that flips the minting reaches users, or an old client reads a new spool as a real chip and shows the wrong tier — `renderer/inventory.js` (+ mobile, Hub, backend) |
14 | 20 |
|
15 | 21 | - **The Add-Product panel's "NFC Data" preview label is now "TigerData"** — value change across all 9 locales (it's a brand name, identical in every language). The key stays `addProductRfidDataLbl` — `renderer/locales/*` |
|
30 | 36 |
|
31 | 37 | ## Fixed |
32 | 38 |
|
| 39 | +- **A YubiKey (or other Yubico security key) is no longer treated as an RFID reader** — plugged in over USB it exposes a PC/SC CCID interface, so `nfc-pcsc` enumerated it exactly like an ACR122U and the app tried to use it as a filament reader (reported by a real user). The reader-registration gate now skips devices whose PC/SC name matches `yubico`/`yubikey`. Deliberately narrow (Yubico only) to avoid excluding a real reader with an unusual name; the general user-controlled mechanism is the reader-selection panel (`docs/READER-SELECTION-BRIEF.md`) — `services/nfc-process.js` |
| 40 | + |
33 | 41 | - **The Add-Product panel's NFC Data preview is now filled on open** (debug mode). The panel builds the preview whenever a field changes, but on open every one of those refreshes ran *before* the section was un-hidden, so each hit the hidden-section early-return and did nothing — the field stayed empty until the first manual change. `openAddProductPanel` now runs one refresh right after un-hiding the section, so the default product (Generic PLA Basic, 1000 g) renders straight away — `renderer/inventory.js` |
34 | 42 |
|
35 | 43 | - **The step badges in the calibration modal's "How to measure" strip now sit at the top of every card** — the head was `align-items: center`, so a caption that wrapped to two lines (steps 2 and 3, "Keep the cardboard core" / "Put it all on the scale") dropped its orange number badge to the vertical middle while step 1's one-line caption kept its badge at the top. Switched to `align-items: flex-start` so the badge pins to the first line regardless of wrap, plus a −2px nudge so the 18px badge's centre sits level with the 14px caption line rather than 2px below it. Verified the three badges land at delta 0.00 from the first-line centre — `renderer/css/60-modals.css` |
|
43 | 51 |
|
44 | 52 | ## Removed |
45 | 53 |
|
| 54 | +- **The "I own a TigerPOD" toggle** in the TigerPOD modal, with its `tigerPodOwnLabel` / `tigerPodOwnSub` i18n keys and `.tigerpod-own-card` CSS. It was redundant: `hasPod` is a telemetry-only flag (`telemetry/studio.hasPod`) that **nothing in the app behaviourally depends on**, and it is auto-set on the first successful RFID read with readers — so a manual toggle changed nothing the next scan wouldn't re-set. The auto-set (and the whole 1-or-2-reader write path) is untouched — `renderer/inventory.html`, `renderer/inventory.js`, `renderer/css/60-modals.css`, i18n (2 keys × 9 locales) |
| 55 | + |
46 | 56 | ## i18n |
0 commit comments