Skip to content

Commit bff8690

Browse files
committed
v2.17.2 — real spool size on product cards, 7 552-product catalogue
Added: - Product card shows the material's colours (one hex per line, all slots) and its quantity as the product states it (2 kg, not 2000 g). The alpha is never invented: a RRGGBB catalogue colour is completed from the chip's own color_a when present, left as-is otherwise — a TigerTag+ can carry any factory alpha. - Raw-JSON block (with copy) at the bottom of the product card in debug mode. - Bundled catalogue refreshed to 7 552 products (was 4 807) + brand table. Fixed: - Product card hardcoded a 1 kg capacity, so every 500 g / 750 g / 2 kg product read "1000 g". One render function serves all six entry points, so every product card in the app was affected. - _catalogDocFromApi read measure_value and grams into one variable and then converted by unit — a missing measure_value on a kg product would have given 2000 x 1000 g. `grams` is now the authority for measure_gr. - Refill / Recycled / Filled badges were built then never inserted (dead code); they now render on both the spool and the product card. - Detail rows: a long SKU ran off the card edge, a medium one wrapped with half the row empty (max-width 60% replaced by proper flex sizing). - build:mac:unsigned / build:all did not generate the Google OAuth config.
1 parent ec3bfb8 commit bff8690

21 files changed

Lines changed: 66249 additions & 2474 deletions

‎CHANGELOG.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ Versions follow [Semantic Versioning](https://semver.org/).
55

66
---
77

8+
## v2.17.2 — 2026-08-02
9+
10+
### Added
11+
12+
- **Product card: colour, quantity, and a raw-JSON block in debug mode.** DÉTAILS gained a **Color** row listing every slot as `#RRGGBBAA`, one per line (a dual/tri product shows all of them, not just the first) and a **Quantity** row showing the product's own `measure` with its unit — `2 kg`, not the `2000 g` the gauge uses. The alpha is never invented: a catalogue colour given as `RRGGBB` is completed from the chip's own `color_a` byte when the record has one, and left as-is otherwise — a TigerTag+ can be factory-set to any alpha, so padding with `FF` would have been a guess. With debug mode on, the card ends with the same collapsible **raw JSON** block (and copy button) the material side-card has — `renderer/inventory.js`.
13+
- **Bundled catalogue refreshed to 7 552 products** (was 4 807), plus a brand-table update, via `assets/db/tigertag/db_update.py` — `assets/db/tigertag/`.
14+
15+
### Fixed
16+
17+
- **The product card always showed a 1 kg spool, whatever the real size.** `_renderProductCard` hardcoded `const cap = 1000, curW = 1000`, so a 500 g, 750 g or 2 kg product all read "1000 g / 1 kg total" with a full bar — while the grid card right beside it showed the correct `500 g`. The capacity was never missing: the catalogue seed already carries it and `normalizeRow` exposes it as `r.capacity`. The card now uses that, falling back to parsing the catalogue item's display string (`"500 g"` / `"2 kg"`, new `_catMeasureToGrams`) for a preview opened before the API detail lands. The spool still renders FULL — a product identity has no per-spool weight — only its capacity is now real. **One render function serves all six product-card entry points** (catalogue, favourites, lists, cart, friend view, groups), so every card in the app was affected and is fixed by this — `renderer/inventory.js`.
18+
- **Catalogue seed: `measure_value` and `grams` are two different quantities and were read into one variable.** `_catalogDocFromApi` did `Number(fil.measure_value ?? fil.grams)` and ran the result through the unit conversion — but `measure_value` is unitless and only means something with `measure_unit` (500 + "g", or 2 + "kg"), while `grams` is ALREADY normalised by the API. A missing `measure_value` on a kg product would have yielded 2000 × 1000 g. `grams` is now the authority for `measure_gr`; the raw `measure_value` (paired with `id_unit`) is kept for the chip payload as the `.ttag` contract requires, and the conversion only runs when the API omits `grams` — `renderer/inventory.js`.
19+
- **The Refill / Recycled / Filled badges were never displayed anywhere.** The spool detail card computed `infoBadges` and built `infoHtml2` from them, then never inserted it into its template — dead code (eslint had been flagging the unused variable), which is why a "PLA Basic Refill" spool showed no badge at all. Inserted into the Details body, and the same three chips added to the **product card** — same `.aspect-chip` markup and the same existing `badgeRefill`/`badgeRecycled`/`badgeFilled` keys, already translated in all 9 locales. They read `info1`/`info2`/`info3` through `normalizeRow` — `renderer/inventory.js`.
20+
- **Side-card detail rows: a long value ran off the edge, and a medium one wrapped with half the row empty.** `.panel-row .pv` was capped at `max-width: 60%`, so a SKU broke onto two lines even when the label beside it was short and the space free; and nothing could break an unbreakable string (a SKU or barcode has no spaces), so a long one overflowed past the right edge. The label is now `flex: 0 0 auto` and the value `flex: 1 1 auto; min-width: 0`, plus `overflow-wrap: anywhere` for the no-space case. Applies to every panel row, so the material card benefits too — `renderer/css/70-detail-misc.css`.
21+
- **`build:mac:unsigned` and `build:all` shipped without Google OAuth credentials** — the generator added in v2.17.1 was only wired into the publishing builds, so a local or unsigned build had no `oauth-config.json` on a clean checkout — `package.json`.
22+
23+
---
24+
825
## v2.17.1 — 2026-08-02
926

1027
### Fixed

‎FEATURES.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Tiger Studio Manager — Feature Catalogue
22

3-
Tiger Studio Manager is the Electron desktop companion to the TigerTag ecosystem: a filament-inventory manager built around RFID/NFC-tagged spools ("TigerTag" chips), a fully-digital "TigerData" tier (and its catalogue-identified "TigerData+" rung), live 3D-printer integration across six brands, physical storage/rack management, a Firebase-backed social layer (friends, shareable wishlists, public profiles), and companion hardware (TD1S color sensor, TigerScale, TigerPOD dual-reader stand). This document catalogues every **shipped** feature, grouped by domain, current as of **v2.17.0**. Per-version release detail lives in `CHANGELOG.md`; forward-looking / in-progress work lives in `ROADMAP.md`.
3+
Tiger Studio Manager is the Electron desktop companion to the TigerTag ecosystem: a filament-inventory manager built around RFID/NFC-tagged spools ("TigerTag" chips), a fully-digital "TigerData" tier (and its catalogue-identified "TigerData+" rung), live 3D-printer integration across six brands, physical storage/rack management, a Firebase-backed social layer (friends, shareable wishlists, public profiles), and companion hardware (TD1S color sensor, TigerScale, TigerPOD dual-reader stand). This document catalogues every **shipped** feature, grouped by domain, current as of **v2.17.2**. Per-version release detail lives in `CHANGELOG.md`; forward-looking / in-progress work lives in `ROADMAP.md`.
44

55
---
66

‎WORKLOG.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
# Worklog — v2.17.1 (in progress)
1+
# Worklog — v2.17.2 (in progress)
22

33
## Added
4+
- **Product card: HEX colour, quantity, and a raw-JSON block in debug mode.** DÉTAILS gained a **Color** row listing every slot as `#RRGGBB`, one per line, alpha normalised to `RRGGBBAA` (a dual/tri product shows all of them, not just the first) and a **Quantity** row showing the product's own `measure` with its unit — `2 kg`, not the `2000 g` the gauge uses. With debug mode on, the card now ends with the same collapsible **raw JSON** block (and copy button) the material side-card has, so a catalogue product's seed can be inspected without leaving the card — `renderer/inventory.js`.
45

56
## Changed
6-
- **`productKey` changed meaning in v2.17.0 and no data-model doc said so.** It is the join key third parties, the Hub and the backend statistics use, and since the tier left the key a `TigerData+` document now hashes to the same value as the `TigerTag+` of its `id_product`. Documented in `docs/firestore-schema.md` and propagated to the public integration reference (the backend repo's README): which documents change value (only `TigerData+`), that every other tier keeps its hash, that the mirror rewrites them lazily so BOTH values are in the wild during the rollout — the same caveat `protocol` already carries — and what a reader should do about it — `docs/firestore-schema.md`.
7-
8-
- **Signing in with Google is near-instant when a browser session is already open.** The loopback flow forced `prompt=select_account` on every sign-in, which made Google re-authenticate from scratch each time — account chooser plus a full identity challenge (passkey / security key / password) even with a live session in the browser. Dropped the parameter: an existing session now completes the round-trip with little or no interaction. Multi-account users are unaffected in practice — Google shows the chooser on its own whenever the browser holds more than one session — `main.js`.
97

108
## Fixed
11-
- **Google sign-in works again — regression live since v1.10.0.** Commit `a94b4aa` (2026-05-20) moved the Google Desktop OAuth credentials to `process.env.…` with no fallback. `main.js` reads them at **runtime**, on the user machine, where they never exist: CI only sets them at **build** time and, with no bundler and no `afterPack` hook, nothing inlined them — so **every shipped build** ran with empty credentials. The loopback flow (RFC 8252 + PKCE, system browser) then reported "not configured" and the renderer silently fell back to `signInWithPopup`, which Google refuses from an embedded Electron webview. Credentials are now written by **`scripts/gen-oauth-config.mjs`** into a gitignored `oauth-config.json` that electron-builder packs into the app, and `main.js` resolves them **env → generated file → hardcoded public client id**. The client id keeps a hardcoded fallback (public by design, already in the repo history); the **client secret has none** — it must never enter the public repository, even though it necessarily ships inside the binary (RFC 8252 §8.5: an installed app cannot keep a secret; PKCE is what protects the exchange). Google **requires** that secret for this Desktop client — verified against the live endpoint, which answers `invalid_request / client_secret is missing.` without it — so the `client_secret` field stays in the token exchange, with a comment saying why. The "not configured" guard now checks **both** credentials and names the missing one, so a misconfiguration fails fast in the log instead of surfacing as a mysterious popup — `main.js`, `scripts/gen-oauth-config.mjs`, `package.json`, `.gitignore`.
9+
- **The Refill / Recycled / Filled badges were never displayed anywhere.** The spool detail card computed `infoBadges` and built `infoHtml2` from them, then never inserted it into its template — dead code, which is why a "PLA Basic Refill" spool showed no badge at all (eslint had been flagging the unused variable). Inserted it into the Details body, and added the same three chips to the **product card** (same `.aspect-chip` markup and the same existing `badgeRefill`/`badgeRecycled`/`badgeFilled` keys, already translated in all 9 locales — no new key, no new CSS). They read `info1`/`info2`/`info3` through `normalizeRow` (`isRefill`/`isRecycled`/`isFilled`) — `renderer/inventory.js`.
10+
- **Side-card detail rows: a long value ran off the edge, and a medium one wrapped with half the row empty.** `.panel-row .pv` was capped at `max-width: 60%`, so a SKU broke onto two lines even when the label beside it was short and the space was free; and nothing could break an UNBREAKABLE string (a SKU or barcode has no spaces), so a really long one overflowed past the right edge. The label is now `flex: 0 0 auto` and the value `flex: 1 1 auto; min-width: 0` — it takes all the free space and only wraps when it genuinely has to — plus `overflow-wrap: anywhere` for the no-space case. Applies to every panel row, so the material card benefits too — `renderer/css/70-detail-misc.css`.
11+
- **Catalogue seed: `measure_value` and `grams` are two different quantities and were read into one variable.** `_catalogDocFromApi` did `Number(fil.measure_value ?? fil.grams)` and then ran the result through the unit conversion — but `measure_value` is unitless and only means something with `measure_unit` (500 + "g", or 2 + "kg", or a volume), while `grams` is ALREADY normalised by the API. A missing `measure_value` on a kg product would therefore have yielded 2000 x 1000 g. `grams` is now the authority for `measure_gr`, and the raw `measure_value` (paired with `id_unit`) is kept for the chip payload as the `.ttag` contract requires; conversion only runs when the API omits `grams`. Verified on four live products, including the failing path — `renderer/inventory.js`.
12+
- **The product card always showed a 1 kg spool, whatever the real size.** `_renderProductCard` hardcoded `const cap = 1000, curW = 1000`, so a 500 g, 750 g or 2 kg product all read "1000 g / 1 kg total" with a full bar — while the grid card right next to it showed the correct `500 g`. The capacity was never missing: the catalogue seed already carries it (`_catalogDocFromApi` sets `measure`/`measure_gr` from the API `measure_value`+`measure_unit`, falling back to `grams`), and `normalizeRow` exposes it as `r.capacity`. The card now uses it, falling back to parsing the catalogue item's display string (`"500 g"` / `"2 kg"`, new `_catMeasureToGrams`) for a preview opened before the API detail lands, then to 1 kg. The spool still renders FULL — a product identity has no per-spool weight — only its capacity is now real. **One render function serves all six product-card entry points** (catalogue, favourites, lists, cart, friend view, groups), so every card in the app was affected and is fixed by this. Verified against the live API: 500 g -> 500, 2 kg -> 2000, 750 g -> 750 — `renderer/inventory.js`.
13+
14+
## Removed
15+
16+
## i18n

‎assets/db/tigertag/id_brand.json‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@
119119
142
120120
]
121121
},
122+
{
123+
"id": 5048,
124+
"name": "Marswork",
125+
"type_ids": [
126+
142
127+
]
128+
},
122129
{
123130
"id": 6305,
124131
"name": "Markforged",
@@ -583,6 +590,13 @@
583590
142
584591
]
585592
},
593+
{
594+
"id": 38953,
595+
"name": "Tucab",
596+
"type_ids": [
597+
142
598+
]
599+
},
586600
{
587601
"id": 39002,
588602
"name": "GreenGate3D",

0 commit comments

Comments
 (0)