Skip to content

Commit 4ccb7dc

Browse files
committed
v1.8.4 — Fix TigerCloud date & twin double-count, consistent view toggles, geo telemetry
- Fix: TigerCloud "Manufactured" date (~2056) — write chip-epoch (since-2000) timestamp on Cloud creation; fmtChipTs defensively corrects legacy docs - Fix: Storage counted twin pairs twice (not-stored list/count, free slots, per-rack count, auto-fill scatter) — collapse via deduplicateTwins - Change: view toggles — materials order Grid·Table·Storage, both groups share the same Grid/Table icons + i18n keys (fixes FR "Table" vs "Tableau"), Cam localised - Add: telemetry studioCountry + studioTimezone (offline, locale-derived) and langsUsed/countriesUsed lifetime aggregates
1 parent 5398e1f commit 4ccb7dc

15 files changed

Lines changed: 124 additions & 63 deletions

File tree

‎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+
## v1.8.4 — 2026-05-28
9+
10+
### Fixed
11+
12+
- **TigerCloud "Manufactured" date wrong (~2056)** — Cloud spools stored their creation time as a Unix timestamp instead of the TigerTag chip epoch (seconds since 2000), so the decoded manufacturing date overshot by ~30 years. Fixed at creation (Add Product, Duplicate); the display also defensively corrects already-created spools. The stored value is now correct when a Cloud spool is later burned to a physical chip.
13+
- **Storage — linked (twin) spools counted twice** — a twin pair (one physical spool, two tags) now shows and counts **once** in the "not stored" list, the not-stored count, the free-slot count, and each rack's header count (no more over-capacity like `28/27`). Auto-fill no longer scatters the two tags of a twin into separate slots.
14+
15+
### Changed
16+
17+
- **View toggles — consistent icons + order** — the materials toggle is now **Grid · Table · Storage**; both toggle groups share the same Grid (`⊞`) and Table (list) icons and the same translations (fixes the FR mismatch where the printer "Table" stayed untranslated). The printer "Cam" label is now localised.
18+
19+
### Added
20+
21+
- **Usage telemetry — geographic dimension** — alongside the existing version / OS / language / session metrics, the app now records a locale-derived country code and IANA timezone (offline, no IP geolocation), plus lifetime `langsUsed` / `countriesUsed` aggregates, for future usage statistics.
22+
23+
---
24+
825
## v1.8.3 — 2026-05-28
926

1027
### Spool detail — Duplicate (×N)

‎CLAUDE.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,17 @@ users/
252252
studioOsVersion string — human-readable OS (e.g. "macOS 15.4", "Windows 11 Pro")
253253
studioLang string — app language setting (e.g. "fr")
254254
studioLocale string — system locale (e.g. "fr-FR")
255+
studioCountry string — country code derived from the locale region (e.g. "FR"); null when the locale has no region. Offline-derived, no IP geolocation
256+
studioTimezone string — IANA timezone (e.g. "Europe/Paris"), from Intl.DateTimeFormat
255257
studioLastSeen timestamp — server timestamp of last login (deployment targeting / churn)
256258
257259
telemetry/
258260
studio/ — aggregated lifetime metrics (standard Firebase pattern)
259261
sessionsCount number — total sessions (FieldValue.increment)
260262
versionsUsed string[]— all app versions ever used (FieldValue.arrayUnion)
261263
platformsUsed string[]— all platforms ever used (FieldValue.arrayUnion)
264+
langsUsed string[]— all app languages ever used (FieldValue.arrayUnion)
265+
countriesUsed string[]— all country codes ever seen (FieldValue.arrayUnion; only when derivable)
262266
lastSeen timestamp — server timestamp of last session
263267
td1sUsed boolean — true once a TD1s sensor was ever connected
264268
rfidReadersMax number — max simultaneous RFID readers ever seen (1 or 2)

‎WORKLOG.md‎

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,33 @@
1-
# Worklog — v1.8.3 (in progress)
1+
# Worklog — v1.8.4 (in progress)
22

33
## Added
44

5-
- **Detail panel — inline editable spool name (`message` field)** — `renderer/inventory.js`, `renderer/css/70-detail-misc.css`
6-
- Identity block restructured: **Brand · Series · Material on line 1**, the message (name) on its own full-width line below (text left, edit pencil pinned right) — clearer and roomier than sharing the Material line.
7-
- The editable message is available on **every spool type** (Cloud, basic, TigerTag+) outside friend view. On TigerTag+ the catalogue name (e.g. "Artic Teal") stays read-only on its own line and the editable message renders below it as a lighter secondary label; on Cloud/basic the message IS the spool name. Writes the `message` chip slot; Enter/blur saves, Escape cancels. It's a free-text note (placeholder "Add a note"). Same 28-byte UTF-8 cap as the Add Product colour-name field, with a thin usage bar under the input that fills as the byte budget is consumed (blue → amber ≥80% → red when full; no number shown).
8-
- Editing the message is a chip change (it lives in the chip's color_name slot): it now flags `needUpdateAt` (twin-aware) just like TD / colour edits, so the chip-update badge + re-burn banner appear. Skipped for Cloud spools (no physical chip).
9-
- **Toolbox — Duplicate spool (×N)** — `renderer/inventory.js`, `renderer/css/70-detail-misc.css`
10-
- New "Duplicate" tool (first toolbox row, hold-to-confirm 1s) with a − N + quantity stepper (1–50): mint one or many copies in a single batched write. Main label tracks the count ("Duplicate ×N"); in-place confirmation flashes in the label.
11-
- Each copy is a fresh `CLOUD_` doc, identical to the source (same `id_tigertag`, colour, material…) except a unique Cloud UID. Shown for TigerCloud and basic TigerTag spools; hidden for TigerTag+ (not duplicable). A basic TigerTag necessarily becomes Cloud (a digital clone has no physical chip).
12-
- No twin link, no rack placement survive the clone (nothing physical exists in a Cloud entry). Twin-conflict avoidance: copies are spaced **+3s** apart on `timestamp` (and past the source's own timestamp) so the 2s-window twin auto-linker never pairs identical copies — the timestamp doubles as the twin-pairing key.
13-
- Split-row render now supports a hold-to-confirm main button; Duplicate uses a blue (constructive) hold fill instead of the red danger tint.
14-
- **Bambu printer models: `camera_transport` field + X2D** — `data/printers/bbl_printer_models.json`
15-
- Added `"camera_transport": "rtsp"` / `"jpeg_tcp"` on every entry; single source of truth for JPEG TCP vs RTSP camera detection
16-
- Added X2D (ID `"12"`, `camera_transport: "rtsp"`, image X1C placeholder)
17-
- **README: TigerPOD section** — dedicated subsection with embedded video, feature table, and MakerWorld download link — `README.md`
18-
- **README: Open source ecosystem section** — table of all 4 open source components (Studio Manager, SDK JS, TigerScale, TigerPOD) with repo links, licenses, and SDK description — `README.md`
19-
- **README: Screenshots section** — 6 app screenshots in 3×2 grid (inventory, printers, racks, cam, TD1S, TigerPOD) replacing "coming soon" — `README.md`, `assets/img/screenshots/`
20-
- **README: TigerPOD video** — replaced `<video>` tag with clickable thumbnail (`screenshot_tigerpod.png`) linking to the mp4 — `README.md`
21-
- **README: TD1S section** — photo (`TD1S_Front.png`) added above feature description — `README.md`
22-
- **README: TigerScale section** — photo (`TigerScale_Photo.png`) added above feature list — `README.md`
23-
- **README: Storage / Racks section** — 4 rack preset photos added (Standard, Extended, Mini, Box 6), feature list expanded with rack presets mention — `README.md`
5+
- **Telemetry — country + timezone + language aggregates** — `renderer/inventory.js`, `CLAUDE.md`
6+
- Added `studioCountry` (locale region, e.g. "FR" — derived offline from `navigator.language`, no IP geolocation) and `studioTimezone` (IANA tz) to the per-session `users/{uid}` telemetry write.
7+
- Added lifetime aggregates `langsUsed` + `countriesUsed` (arrayUnion) to `users/{uid}/telemetry/studio`.
8+
- Note: language was already persisted (`prefs/app.lang` cross-device + `studioLang`/`studioLocale` per session); OS / version / arch / sessions were already tracked. This adds the missing geo dimension.
249

2510
## Changed
2611

27-
- **ROADMAP: new entry "Printer slot storage — assign filaments to machine slots (dual-location)"** — `ROADMAP.md`
28-
- Spec'd the feature: on printer connect, materialise virtual storage mirroring the machine's feed slots (Ext./AMS/AMS-HT…); assign inventory spools to slots like racks, but as a second simultaneous location (`mount` field) that never clears the rack home; right-click → printer → slot assignment with eviction-on-occupied; dual-location indicators in the filament list. Data model, sub-features P1–P5, reuses, debug surface, dependencies.
29-
- Refined: slots are **persisted on the printer device doc** (seeded on connect, reconciled on accessory add/remove, deleted only when the printer is removed), keyed by a **stable hardware id** (AMS serial) for reliable recognition across reconnects, with a `present` flag (absent ≠ deleted) so temporary disconnects don't wipe assignments.
30-
- Clarified: **slots stay active even when the printer is offline/disconnected** — connection state is orthogonal to slot availability (`present` tracks the accessory, not the link). Assignment menu + slot boards target every printer in inventory regardless of connection; reconciler only runs while connected.
31-
- Model change: **the printer owns occupancy** — each slot stores the spool UID(s) (`uids`: 1 for a plain spool, 2 for a twin pair) on the printer doc; no `mount` field on the spool. Eviction is intrinsic (overwrite the slot's `uids`); mount state is a derived in-memory `uid → slot` index rebuilt on each `state.printers` snapshot.
32-
- Firestore-rules note: owner path needs no new rule (own subtree); optional `uids` shape validation as hardening.
33-
- Added sub-feature **P6 — share printer fleet + slot contents with selected friends**: per-friend `sharePrinters` opt-in on the owner's `friends/{uid}` doc, Firestore read grant on `printers/**` gated by the existing friendship key **plus** `sharePrinters == true`, read-only slot boards in friend view (uids resolved against the friend's already-readable inventory), immediate revocation. Adjusted the Friend-view + Firestore-rules notes accordingly.
34-
- **Rename "TigerTag Cloud" → "TigerCloud"** — across the app (badge labels, stat tile, `protocol`/filter value, comments), all 9 locales (`statCloud`, `toolDuplicateTip`), CSS, and docs (README, ROADMAP, CHANGELOG, DEVLOG). `protocol` and stat `filter` stay matched so the Type quick-filter keeps working.
35-
- **Bambu camera transport: JSON-driven instead of hardcoded** — `renderer/printers/bambulab/index.js`
36-
- Removed `_SERIAL_PREFIX_MODEL` and `_JPEG_CAM_IDS` hardcoded sets
37-
- `bambuUsesJpegCam(p)` now reads `camera_transport` from `bbl_printer_models.json` via `ctx.findPrinterModel`
38-
- `bambuModelId(p)` simplified: returns `parseInt(printerModelId)` with no serial-prefix fallback
12+
- **View toggles — consistent icons + materials order** — `renderer/inventory.html`, locales
13+
- Materials toggle reordered to **Grid · Table · Storage** (was Table · Grid · Storage). Printer toggle order unchanged.
14+
- Unified the icons across both groups: the **Grid** button now shows the same `⊞` glyph in both (printer Grid switched from the printer icon to `⊞`), and the **Table** button uses the same `icon-list` SVG in both (materials Table switched from the `☰` glyph to `icon-list`).
15+
- i18n `btnViewTable` no longer carries the `☰` glyph (now rendered as an SVG icon) — 9 locales.
16+
- i18n consistency: both groups now **share the same keys** (no double translation) — Grid → `btnViewGrid`, Table → `btnViewTable`. Fixed the FR mismatch where the printer Table was hardcoded "Table" while materials showed "Tableau". Printer Cam is now translated via a new `btnViewCam` key (was hardcoded). The leftover orphan key `btnViewPrinter` ("Imprimantes") is unused (left as-is — no i18n remove script).
3917

4018
## Fixed
4119

42-
- **Printers table — Bambu IP not shown** — `renderer/inventory.js`
43-
- Bambu printers store their IP in `p.broker` (MQTT broker address), not `p.ip`
44-
- Table cell and IP sort column now use `p.ip || p.broker` so Bambu IPs appear correctly
20+
- **TigerCloud "Manufactured" date wrong (~2056)** — `renderer/inventory.js`
21+
- Cloud docs were created with a Unix timestamp (seconds since 1970), but the TigerTag standard + `fmtChipTs` use seconds since 2000 — so the decoded date over-shot by ~30 years. Added `nowChipTs()` (chip-epoch seconds) and use it on every Cloud `timestamp` write (Add Product preview + save, Duplicate). This also makes the value correct when the Cloud doc is later burned to a physical chip.
22+
- `fmtChipTs` now defensively folds a stray Unix-epoch value back to the 2000 epoch (threshold ~year 2044), so already-created buggy docs display the correct date too. Duplicate normalises a legacy source timestamp before staggering.
23+
- **Storage — twin pairs double-counted** — `renderer/inventory.js`
24+
- `getUnrackedSpools()` now collapses twin pairs (`deduplicateTwins`): a linked spool (one physical spool, two tags) shows once in the "not stored" list and counts once (not-stored count + side count + auto-fill pool).
25+
- Slot counts deduped too: total filled slots (→ correct "free" count) and per-rack header count (no more `28/27` over-capacity).
26+
- Side effect fixed: auto-fill no longer places the two tags of a twin into two separate slots (the pool is now deduped, and assignment already mirrors the rack to both docs via `writeWithTwin`).
4527

4628
## Removed
4729

4830
## i18n
4931

50-
- Added: `toolDuplicate`, `toolDuplicateTip`, `toolDuplicateOk`, `toolDuplicateCount`, `msgEditTip`, `msgEditAdd` — 9 locales
32+
- Added: `btnViewCam` — 9 locales
33+
- Changed: `btnViewTable` dropped the leading `☰` glyph (now an SVG icon) — 9 locales

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tigertag-inventory",
3-
"version": "1.8.3",
3+
"version": "1.8.4",
44
"description": "Tiger Studio Manager — desktop app",
55
"main": "main.js",
66
"engines": {

‎renderer/inventory.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,15 @@
186186
<div class="inv-view-row">
187187
<div class="view-toggle-groups">
188188
<div class="view-toggle">
189-
<button id="btnViewTable" class="active" data-i18n="btnViewTable">☰ Table</button>
190189
<button id="btnViewGrid" data-i18n="btnViewGrid">⊞ Grid</button>
190+
<button id="btnViewTable" class="active"><span class="icon icon-list icon-13"></span><span data-i18n="btnViewTable">Table</span></button>
191191
<button id="btnViewRack"><span class="icon icon-package icon-13"></span><span data-i18n="btnViewRack">Storage</span></button>
192192
</div>
193193
<span class="vtg-sep" aria-hidden="true"></span>
194194
<div class="view-toggle vtg-printers">
195-
<button id="btnViewPrinter"><span class="icon icon-printer icon-13"></span><span>Grid</span></button>
196-
<button id="btnViewPrinterTable"><span class="icon icon-list icon-13"></span><span>Table</span></button>
197-
<button id="btnViewCam"><span class="icon icon-eye-on icon-13"></span><span>Cam</span></button>
195+
<button id="btnViewPrinter" data-i18n="btnViewGrid">⊞ Grid</button>
196+
<button id="btnViewPrinterTable"><span class="icon icon-list icon-13"></span><span data-i18n="btnViewTable">Table</span></button>
197+
<button id="btnViewCam"><span class="icon icon-eye-on icon-13"></span><span data-i18n="btnViewCam">Cam</span></button>
198198
</div>
199199
</div>
200200
<div class="inv-actions-group">

0 commit comments

Comments
 (0)