d02e48543f
- Bump header-version in index.html to v1.7.1 - Bump manifest.json version to 1.7.1 - Update CHANGELOG with v1.7.1 release notes Includes: - Destructive confirm modal with 5s auto-countdown (throwAll, submitUseAll) - Undo button visibility fix in history log - undoTransactionEntry() uses custom modal instead of native confirm()
16 KiB
16 KiB
Changelog
All notable changes to EverShelf will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.7.1] - 2026-05-04
Fixed
- Destructive actions now require confirmation — "Butta tutto" (
throwAll) and "Finisci tutto" (submitUseAll) now display a confirmation modal before executing. The modal features a 5-second auto-confirm countdown bar (red) with an "Annulla" cancel button, matching the scale auto-confirm UX pattern already in use. - History undo button visibility — The ↩ undo button in the transaction log was using
color: var(--text-muted)making it nearly invisible. It now uses a red tint background + border (#f87171) with larger font size (1rem) for easy tap targeting. - History undo uses custom modal —
undoTransactionEntry()previously used the native browserconfirm()dialog (broken in Android WebView kiosk mode). It now uses the same_showDestructiveConfirm()modal with countdown.
Added
- Demo mode (JS frontend) — Full client-side demo experience: Gemini is treated as available, Bring! write operations silently no-op, and a mock pantry + shopping list is shown; activated via
?demo=1URL param or.envDEMO_MODE=true; a "DEMO" badge is injected in the header and Settings is hidden to prevent accidental writes - Graceful Bring! no-key state — When Bring! credentials are not configured the shopping tab shows a friendly localised message with a direct link to the Settings page instead of a raw API error
- Use-quantity guard — Consuming more than the quantity stocked at the selected location is now blocked before the API call; the quantity input shakes (CSS
input-shakeanimation) and a toast showsuse.error_exceeds_stock - Kiosk: smart auto-discovery rewrite —
autoDiscover()now usesExecutorCompletionService+NetworkInterface(replaces deprecatedWifiManager), 60 parallel threads, 600 ms TCP pre-check per host, real-time UI feedback every 120 ms, ports[443, 80, 8080, 8443]; VPN/cellular interfaces (tun, ppp, rmnet, pdp, ccmni, etc.) are filtered out andwlan*/eth*interfaces are prioritised - Kiosk: permissions button transform — After permissions are granted, the button changes to "✅ Permessi concessi — Continua →" (green background, dark text) and advances to step 3 on tap, replacing the separate "permissions granted" card
- Kiosk: gateway auto-pre-configuration — On successful gateway install
finishSetup()POSTsscale_enabled=true+scale_gateway_url=ws://127.0.0.1:8765to the server'ssave_settingsendpoint so the webapp is scale-ready immediately after setup - Kiosk: ErrorReporter init at setup start —
SetupActivity.onCreate()now callsErrorReporter.init()with any previously saved URL, ensuring errors in step 4 (gateway install) are reported even before the user confirms the server URL
Fixed
- Kiosk: wrong subnet scanned — The previous implementation picked up VPN/tun interfaces and scanned a 10.x.x.x range instead of the device's actual Wi-Fi LAN; fixed by filtering interface names and preferring
wlan/eth - Kiosk: port 443 missing from discovery — HTTPS servers were never reachable during auto-discovery; ports list extended to
[443, 80, 8080, 8443] - Kiosk: gateway install status=1 silent failure —
PackageInstaller.STATUS_FAILURE(status 1) showed an error card but never calledErrorReporter;ErrorReporter.reportMessage()is now called with status code, message, and package name - Screensaver toggle in web settings — The screensaver row was missing a
<span class="toggle-slider">inside the<span class="toggle-switch">wrapper, so no slider was rendered; corrected to use the sametoggle-row/toggle-switch/toggle-sliderstructure as all other settings toggles - antiwaste.title translation — IT and DE locale files were missing the
antiwaste.titlekey, causing a raw key string to appear in the anti-waste section header; added to bothit.jsonandde.json
Kiosk (v1.4.0 → v1.5.0)
autoDiscover()fully rewritten (CompletionService, NetworkInterface, TCP pre-check, real-time feedback, correct LAN subnet)- Port 443 added to discovery scan
- Permissions button transforms after grant (
onPermissionsGranted()) ErrorReporter.init()called atSetupActivity.onCreate()ErrorReporter.reportMessage()called on gateway install failurefinishSetup()pre-configures gateway viasave_settingsAPI call
[1.6.0] - 2026-05-03
Added
- Dashboard skeleton loading — Stat cards (Dispensa / Frigo / Freezer) show an animated shimmer placeholder (
…) instead of the jarring0flash that appeared for 3–5 seconds before data loaded; the loading class is applied before the API call and removed atomically when data arrives - Webapp startup preloader — Full-screen spinner overlay during initial app load, fades out after the dashboard is ready
- Webapp update notification — A dismissible top banner alerts the user when a newer GitHub release is available (checked once every 6 hours, comparison based on
published_at) - Native Android update banners — Both Kiosk (v1.4.0) and Scale Gateway (v2.1.0) show a native top bar when a newer APK is available, with one-tap download and install
Fixed
- APK install conflict — Replaced
ACTION_VIEW-based APK install with thePackageInstaller.SessionAPI (API 21+) in both Kiosk and Scale Gateway; the session-based approach correctly handles:STATUS_PENDING_USER_ACTION→ automatically launches the system confirmation dialogSTATUS_SUCCESS→ success toastSTATUS_FAILURE_CONFLICT/STATUS_FAILURE_INCOMPATIBLE→AlertDialogoffering to uninstall the old app (signature mismatch) before reinstalling
- Cooking mode z-index — Update banner and app header are now hidden when
body.cooking-mode-activeis set, and the cooking overlay z-index was raised to99998so it can no longer be obscured by UI chrome - Version-aware error reporting — GitHub Issues are only created when the client is running the latest released version, avoiding noise from stale deployments; non-semver tag names (e.g.
"latest") are treated as "always up-to-date" - XOR-obfuscated GitHub token — The PAT used for GitHub API calls is stored as an XOR-encoded hex string in both the PHP backend and Kotlin apps to prevent accidental exposure via secret scanning
Kiosk (v1.3.0 → v1.4.0)
- FileProvider +
REQUEST_INSTALL_PACKAGESpermission added - APK download destination moved to
getExternalFilesDir(null)(no storage permission needed) PackageInstallerself-update with signature-conflict recovery- BLE scale gateway update banner with download + install flow
Scale Gateway (v2.0.0 → v2.1.0)
- Same FileProvider + permission +
PackageInstallerchanges as Kiosk - Update banner for self-update
- CI workflow now triggers on
developbranch (in addition tomain)
[Unreleased] - 2026-04-30
Fixed
- Low-qty banner false positive — A "suspiciously low quantity" review alert is now suppressed for a partially-used inventory entry when one or more sibling entries for the same product (identified by barcode, or name+brand as fallback) exist in other locations with stock > 0. Prevents noise like "191 ml of milk" when 11 sealed packages are stored in the pantry.
Changed
- Non-alarmist expired banner — Banner icon, CSS class, and title suffix now adapt to the
getExpiredSafety()level:ok(long-life products, freezer within margin): green banner, ✅ icon, "— Scaduto (ancora ok)"warning(items that should be inspected): amber/yellow banner, 👀 icon, "— Scaduto (controlla)"danger(raw meat, dairy, fish, etc.): unchanged red 🚫 banner and "— Scaduto!" title
- Added
expiry.expired_suffix_okandexpiry.expired_suffix_warningi18n keys to all three language files (IT/EN/DE) - Added
banner-expired-okandbanner-expired-warningCSS variants (green / amber) instyle.css
[1.5.0] - 2026-04-28
Added
- Expired banner for opened products — Products whose opened-product shelf-life has passed (e.g. fridge cream opened 6 days ago) now appear in the top notification banner, not just the dashboard list
- Safety-aware expired banner — Each expired banner item shows a contextual safety tip (from
getExpiredSafety()); danger-level items (fridge dairy/meat/fish) get an intense red banner and "L'ho buttato" as the primary button; safe/warning items keep the original button order - AI model fallback — All Gemini API endpoints (expiry scan, product identification, chat, recipe non-streaming, shopping name classifier) now try
gemini-2.5-flashfirst and fall back togemini-2.0-flashautomatically, matching the resilience already in place for recipe streaming - Friendly AI quota message — When the AI returns a quota/rate-limit error the user sees "Quota AI esaurita. Riprova tra qualche minuto." instead of the raw API error string
- Cooking TTS auto-read — Each recipe step is read aloud automatically when navigating forward or backward; the first step is also read when entering cooking mode
- Cooking timer 10-second warning — When a cooking timer reaches 10 seconds the TTS announces "Attenzione! [label]: mancano 10 secondi!"
- Cooking recipe completion announcement — "Ricetta completata! Buon appetito!" is spoken via TTS when the last step is confirmed
Fixed
- Cooking TTS gate —
speakCookingStep()was blocked by the globaltts_enabledsetting; the_cookingTTStoggle (🔊/🔇 button) is now the only gate; browser Web Speech API is used by default without requiring TTS configuration in Settings - Anomaly dismiss label — The "La quantità è giusta" button now appends the current inventory quantity, e.g. "La quantità è giusta (2 pz)", so the action is unambiguous
- i18n sync — Added
timer_warning_tts,recipe_done_tts,error.ai_quotakeys to all three language files (IT/EN/DE)
Added
- Generic shopping names — Products are grouped by type ("Latte", "Affettato", "Pasta") rather than brand; computed via an expanded keyword map with Google Gemini AI as fallback for unknown products
- Bring! auto-migration — Existing list items with old specific names are silently migrated to generic names on every list load, throttled to once per 10 minutes
- Bring! catalog coverage — All 93 shopping_name values now resolve to a German Bring! catalog key (icons and categories in the Bring! app); 24 aliases added to cover previously unmatched names
- Auto-add to Bring! on depletion — When a product reaches zero the app adds it to Bring! automatically using the generic shopping name, with the specific product name and brand in the specification field
- Finished-product confirmation banner — Instead of silently deleting zero-stock entries, a banner prompts the user to confirm; banner title includes the last 3 digits of the product barcode for easier identification
- Anomaly detection banner — Dashboard notifications for suspicious inventory/transaction mismatches and consumption prediction errors, with one-tap inline correction
- SSE recipe streaming — Recipe generation streams live via Server-Sent Events; Gemini agent feedback is shown in real time as it is generated
- Smart alert banners — Configurable expired-only mode with explanatory messages; banner buttons are fully internationalized
Fixed
- Scale double-deduction — Multiple BLE stable readings of the same weight no longer fire duplicate
inventory_useevents; JS preserves the confirmation sentinel on submit and PHP rejects a secondouttransaction for the same product within 12 seconds - Kiosk native TTS — CI workflow now builds the APK on
developbranch too; the native AndroidTextToSpeechbridge bypasses Web Speech API voice-availability issues without requiring offline voice packs - TTS voice loading — Retries for up to 10 seconds on page load; shows a message if no voices are available and offers a manual refresh button
- Bring! migration — Corrected two bugs: wrong removal API (
DELETE /item→PUT remove=item) and wrong purchase key sent to Bring! (Italian shopping name → German catalog key), which previously created Italian/German duplicate entries - Gemini 429 rate limiting — API calls are retried with exponential backoff; recipe requests are capped at 5 per minute with a dedicated rate-limit bucket
Performance
- Gemini calls centralized — All Gemini API requests go through a single
callGemini()helper with intelligent backoff; Gemini removed from the product-selection and bringSuggest flows in favour of fast offline logic
[1.3.0] - 2026-04-18
Added
- Expired product banner — Dashboard notifications for expired products with use, throw away, edit, and dismiss actions
- Expiring soon banner — Dashboard notifications for products expiring within 3 days with use, edit, and dismiss actions
- Priority-sorted notifications — Banner alerts sorted by urgency: expired > expiring > suspicious quantities > consumption predictions
- Swipe navigation — Touch swipe left/right to browse banner notifications, with dot indicators and arrow buttons
- Quick-access buttons — Inventory page shows 4 recently used and up to 8 most popular products for quick selection
- Recent & popular products API — New
recent_popular_productsendpoint - Auto-refresh — Banner notifications refresh every 5 minutes while on the dashboard
- Edit from expiry banner — Correct expiry dates directly from expired/expiring notifications
Fixed
- Negative scale values — BLE scale readings with negative weight are now ignored
- Banner re-appearing after edit — Editing from a banner now persists the confirmation so it doesn't reappear on dashboard reload
- False consumption predictions — Manual inventory edits (updated_at > last restock) now use the correct baseline for prediction calculations
- Kiosk overlay blocking header — Removed injected exit/refresh buttons from the web app header in kiosk mode
[1.2.0] - 2026-04-13
Changed
- Project renamed from "Dispensa Manager" to EverShelf
- Contact email updated to
evershelfproject@gmail.com - Docker service, container, and volume renamed to
evershelf - SQLite database renamed from
dispensa.dbtoevershelf.db - All localStorage keys migrated:
dispensa_*→evershelf_* - Apache config file renamed to
evershelf.conf - CI workflow Docker image/container names updated
- App name updated in all translations (it, en, de)
- Navigation title updated to EverShelf across all languages
Added
- Version badge (
v1.2.0) in the app header
Fixed
- JS file truncation caused by
sedin-place edit on large files - Browser cache invalidation via bumped asset version strings (
?v=20260413a)
[1.0.0] - 2026-04-10
Added
- Complete pantry inventory management (Pantry, Fridge, Freezer, Other)
- Barcode scanning with QuaggaJS
- Open Food Facts barcode lookup
- Google Gemini AI integration (product identification, expiry reading, recipes, chat)
- Bring! shopping list integration
- Smart shopping predictions with cron-based caching
- Cooking mode with step-by-step guidance and TTS support
- Opened product tracking with reduced shelf-life calculation
- Vacuum-sealed product support with extended expiry
- Waste vs. consumption tracking (30-day chart)
- Expired product safety assessment by category
- Weekly meal plan configuration
- DupliClick online grocery ordering integration
- PWA support (installable, mobile-first)
- Local database backup script
- Multi-device settings sync via SQLite
Security
- Centralized
.envconfiguration (secrets never in code) - Removed all hardcoded credentials and personal data
- Input validation on inventory operations
- Parameterized SQL queries throughout