After every develop→main merge, reads the version tag from index.html
(e.g. v1.7.13), checks if that tag already exists, and creates a new
GitHub Release if not. Body is pulled from CHANGELOG.md.
This powers the in-app update badge (`check_update` action) so
self-hosted Docker users see a notification when a new version is
available.
The BLE scale gateway is fully integrated into the EverShelf Kiosk app
since v1.6.0. This standalone Android app is no longer needed or maintained.
Removal also resolves GitHub secret scanning alert #1 (legacy plain-text
GitHub PAT in ErrorReporter.kt — already revoked by GitHub automatically).
Brave browser's anti-fingerprinting user-script (makeFakeVoiceFromVoice)
intercepts the SpeechSynthesis voices array and crashes with
'undefined is not an object (evaluating Object.getPrototypeOf(voice))'
when iterating over null voice entries.
Defensive fix: filter null/undefined/no-lang entries from getVoices()
before processing, so Brave's proxy never receives invalid objects.
Fixes#58
When migrateDB() upgraded the transactions table to add the 'waste'
CHECK constraint, the new table was created WITHOUT the 'undone' column.
The migration then tried to build idx_transactions_pid_type_undone, which
references 'undone' → PDOException SQLSTATE[HY000].
Fix:
- Add undone INTEGER DEFAULT 0 to the migration CREATE TABLE
- Replace 'INSERT INTO transactions SELECT * FROM transactions_old'
with explicit column list (transactions_old may predate undone column)
Fixes: #56
Both PHP and JS rules for opened confettura/marmellata in
section G (fridge condiments) were returning 60 days — too short.
An opened jar of jam lasts ~6 months in the fridge.
Also: update README roadmap with comprehensive, grouped view
matching the internal memory roadmap (high/medium/low/completed).
Fixes: database.php line ~412, app.js line ~1707
- Features.md: translate all Italian UI strings to English (chat examples,
Avvia cottura → Start Cooking, Spiega → Explain, La quantità è giusta → correct)
- Android-Kiosk.md: translate Italian button labels (Concedi permessi →
Grant permissions, Rileva automaticamente → Auto-discover); fix
REQUEST_INSTALL_PACKAGES description (OTA kiosk self-updates, not scale APK);
fix REORDER_TASKS description; add 'Header Overlay Buttons' section documenting
the three web overlay buttons (✕ ↻ ⚙️) and the permanent native button hiding
- Scale-Gateway.md: translate Italian button labels (Cerca Bilance Bluetooth →
Find Bluetooth Scales, Leggi bilancia → Read Scale, Disconnetti/Riconnetti →
Disconnect/Reconnect)
- FAQ.md: translate all Italian strings (AI non disponibile → AI not available,
Bring! non configurato, Leggi bilancia, Carica altri → Load more); replace
outdated 'Gateway install fails' section (separate APK no longer exists for
kiosk users) with 'Kiosk app update fails'; update ✕ button description to
reflect the new 3-button overlay (✕ ↻ ⚙️); restore missing Getting Help section
- Home.md: update What's New v1.7.13 with complete list of changes; mark
evershelf-scale-gateway/ as DEPRECATED in repo structure
- Replace flat .cooking-step-text with a perspective-based cooking wheel
(.cooking-wheel) that shows current step, previous ghost (amber/warm)
and next ghost (blue/cool) in a 3D card-flip layout
- CSS-only 3D: perspective 1100px, rotateX transforms for prev/next ghosts
- Smooth turn-next / turn-prev / snap animations via keyframes
- Float animation on the active step card (subtle translateY loop)
- Radial gradient glow overlay on the wheel container (CSS variable
--wheel-glow) ready for JS tilt interaction
- prefers-reduced-motion: all animations/transitions disabled
- Mobile (<= 640px): smaller min-height and padding adjustments
- gitignore: add data/category_ai_cache.json (runtime AI cache)
- kiosk: add gear button (⚙) to the left overlay (between ✕ and ↻)
so settings are reachable from within kiosk mode without a native
Android button. The web button calls showPage('settings').
- kiosk: permanently hide the native Android settings button via
setNativeSettingsVisible(false) after overlay injection. Removes the
touch bleed-through that caused the camera button tap to open kiosk
settings instead of the scan page.
- kiosk: closeModal() no longer restores native settings visibility
(native button is replaced, must stay hidden)
- dashboard opened-items panel: items expired by opened shelf-life but
classified as safe by getExpiredSafety (level='ok', e.g. jam,
condiments) now show a gentler amber 'Check soon' badge instead of
the red ⛔ 'Scaduto!' that was misleading users. Red ⛔ is now
reserved for warning/danger safety levels only, consistent with the
top banner which already filtered out safe-level expired items.
- header: version label corrected to v1.7.13
- translations: added expiry.badge_check_soon (it/en/de)
Query was missing AND i.quantity > 0, so thrown-away items (qty=0)
with a past expiry_date kept appearing in the expired list.
Also cleaned up the orphan row for Aglio in the DB.
Two changes:
1. Skip prediction when expected_qty=0 — model says 'should be finished'
but user simply restocked or consumed less. Not actionable.
2. Raise 'more than expected' threshold to 400% (was 30%).
Having more than expected almost always means a restock the model
doesn't know about yet — only truly extreme cases (>4x) are flagged.
'Less than expected' stays at 30% (still actionable: unregistered use).
Root cause: baseline was 'restockQty' (only the new items added) but
actualQty = pre-existing stock + new items → always looked like 'more than expected'.
New approach: baseline = current_qty + consumed_since_restock.
This correctly reflects the true starting point regardless of pre-existing stock,
eliminating all false positives after shopping trips.
When a user manually edits quantity (e.g. after restocking), the diff
is recorded as 'in' or 'out' transaction with note '[Correzione manuale]'.
This prevents the anomaly detector from flagging manual edits as phantom
or missing consumption.
When usage splits a row into 'whole sealed packages' + 'opened fraction',
the sealed row was updated without clearing opened_at — if it had been
opened previously, the stale flag would persist and wrongly show
'aperto da N giorni' on intact packages.
Now all 3 split paths (conf early-split, conf post-split, g/ml/l split)
explicitly set opened_at = NULL on the sealed row.
When inventory item has opened_at set, the expired banner now shows:
- Title: '[Nome] — Aperto da troppo tempo!' (instead of '— Scaduto!')
- Detail: 'Aperto da N giorni in [icon] [location] · hai ancora X'
Also removed hardcoded Italian 'scade il' string from non-opened expired detail.
Fresh milk is explicitly matched by 'latte fresco/intero/parzial/scremato' (3 days).
Generic 'Latte' without qualifier is almost always UHT in Italian households — 7 days.