Commit Graph

416 Commits

Author SHA1 Message Date
dadaloop82 13b55104a1 chore: release v1.7.4 — AI price estimation, dashboard badge, real-time total 2026-05-07 17:55:05 +00:00
dadaloop82 bcd7580729 fix: show price total on dashboard via sessionStorage fallback 2026-05-07 17:48:18 +00:00
dadaloop82 1584d402e4 fix: replace stat-urgent with green price total badge top-right 2026-05-07 17:46:20 +00:00
dadaloop82 20192f902d fix: prices cached on tab switch; background price fetch every 2min; stat-price-total bigger 2026-05-07 17:44:56 +00:00
dadaloop82 b9082eae52 fix: log.title emoji; add price estimate total to shopping stat card 2026-05-07 17:41:41 +00:00
dadaloop82 0de9a62058 fix: price estimate for all items, including manually-added ones
- AI prompt: always return a best-guess price (never null/price_not_found)
  for unrecognised items returns generic package estimate with '~' prefix
- Cache key bumped to v3 to invalidate old null-returning cache entries
- JS: manually-added items (no smart match, no spec) default to qty=1/conf
  instead of qty=1/pz so _calcEstimatedTotal treats them as a single pack
- Price badge: shows '~€X.XX' prefix when source_note starts with '~'
  so user knows the price is a rough estimate
2026-05-07 17:38:05 +00:00
dadaloop82 3a9f0ccf79 fix: bump asset versions to force cache bust; price rate limit own bucket
- app.js and style.css versioned to 20260507a so browsers load new code
- get_shopping_price / get_all_shopping_prices moved to dedicated 'price'
  rate-limit bucket (60 req/min) separate from general (120 req/min)
  to avoid false 429s during sequential per-item price loading
2026-05-07 17:34:04 +00:00
dadaloop82 5f510c0451 feat: AI price estimation for shopping list with per-item real-time display
- Add get_shopping_price / get_all_shopping_prices API endpoints
- AI (Gemini) estimates retail price per natural unit (pack, piece, bunch)
  instead of always per-kg — avoids absurd totals like €1609
- _calcEstimatedTotal: proper g/ml→package conversion using defQty + regex
  on unit_label; only 'kg'/'l' labels trigger weight/volume math
- Cache key bumped to v2 to invalidate old per-kg cached entries
- Suggested quantity cap lowered from 20 to 10 conf/pz
- Unit mismatch guard: if totalUsed >> buyCount*5 for unit=conf, use
  purchase frequency instead of raw consumption rate
- JS _buildPricePayload: use smartShoppingItems for qty/unit (not Bring! spec)
- JS _cachedPrices: persist in sessionStorage (survives navigation);
  validated by _qty/_unit metadata so stale totals auto-invalidate
- Price display redesigned: right-side column per row (price-col-main +
  price-col-unit) instead of small inline badge
- fetchAllPrices: buttons disabled immediately before guard check;
  running total uses only current shoppingItems (not Object.values cache)
- Background refresh: always silent (removed 90s interaction condition)
- visibilitychange: sets _bgCall=true for shopping before refreshCurrentPage
- .gitignore: add runtime data files (bring_migrate_ts, shopping_price_cache,
  anomaly_dismissed, opened_shelf_cache, shopping_name_cache)
- Remove bring_catalog.json and bring_migrate_ts.json from tracking
2026-05-07 17:31:23 +00:00
dadaloop82 4196130835 feat: AI suggestions, smart shopping qty, shelf life fixes, UX polish
- bringSuggestItems(): Gemini AI for seasonal/complementary suggestions (6h cache)
- renderSuggestions(): AI badge (🤖 AI) for AI-sourced items + CSS .priority-ai
- smartShopping(): suggested_qty/unit/approx with package-aware tiers
- autoSyncUrgencySpecs(): sync suggested quantities to Bring! spec field
- estimateOpenedExpiryDays(): dairy-outside-fridge rules (panna 3d, yogurt 2d, latte 1d)
- AI shelf-life upper bound tightened to max(rule×4, 30) days
- Opened section: fix 0g display (remainderAmt >= 0.5 threshold, pkgSize guard)
- guessCategoryFromName(): expanded with 50+ new patterns (uova, herbs, vegetables...)
- Suggestions panel: excludes already-added Bring! items
- Shopping list: no re-render while suggestions panel is open
- Translations: remove duplicate 🍳 from dashboard.quick_recipe (all 3 langs)
- Scale icon: always white via filter:brightness(0)invert(1)
- opened_shelf_cache.json: remove 3 bad dairy entries (60d outside fridge)
2026-05-07 06:19:07 +00:00
dadaloop82 ffb0341eb6 feat: screensaver configurable timeout + fix gitignore (exclude kiosk build artifacts) 2026-05-06 15:00:04 +00:00
dadaloop82 725e2ee5ee docs: update README with kiosk v1.7.0 features, OTA signing fix, Actions CI, nutrition dashboard 2026-05-06 14:53:07 +00:00
dadaloop82 8535f4d4b9 fix: update check ignores non-semver tags + GitHub Actions builds versioned releases 2026-05-06 14:41:36 +00:00
dadaloop82 cbb3f6b288 fix: use project keystore for consistent APK signing (fixes OTA update signature conflict) 2026-05-06 14:25:59 +00:00
dadaloop82 484b378be9 fix: kiosk update button works in old APK, shows manual steps if installUpdate missing 2026-05-06 14:22:01 +00:00
dadaloop82 8d0ffef600 fix: kiosk update panel shows manual download link when APK too old 2026-05-06 14:18:29 +00:00
dadaloop82 1c890c66ea feat: kiosk manual update check + install from settings
KioskActivity.kt:
- checkForUpdates(forceCheck, jsCallback): accepts force flag + optional
  JS callback to deliver result as JSON to the WebView
- New @JavascriptInterface checkForUpdates(): bypasses 6h throttle,
  calls back window._kioskUpdateResult({has_update, current, latest, apk_url})
- New @JavascriptInterface installUpdate(apkUrl): triggers APK download+install
- Improved error handling: HTTP status check + network error JSON response

app.js:
- window._kioskUpdateResult(): callback receives update check JSON,
  shows green/amber status box with version info, shows install button
- _kioskCheckForUpdates(): triggers native check, shows spinner while waiting
- _kioskInstallUpdate(): passes apk_url to native installUpdate()
- loadSettings(): shows #kiosk-update-panel when in kiosk WebView

index.html:
- #kiosk-update-panel: version label, 'Cerca aggiornamenti' button,
  status box, 'Installa aggiornamento' button (hidden until update found)
- CSS cache bump ?v=20260506e

build.gradle.kts: version 1.6.0 → 1.7.0 (versionCode 10 → 11)
2026-05-06 14:17:31 +00:00
dadaloop82 891733aa8c fix: scale dot white+glow, kiosk reconfigure fallback, live weight in settings
style.css:
- Connected dot: white fill + green border/glow (was green-on-green, invisible)

app.js:
- _kioskReconfigureScale(): show #kiosk-needs-update-notice + toast when
  kiosk APK is too old and reconfigureScale() method is missing
- _scaleUpdateStatus(): show/hide #scale-live-diag panel, update device + battery
- _scaleOnMessage weight: update #scale-diag-weight in real time
- _scaleOnMessage status: update #scale-diag-proto with BLE protocol

index.html:
- #kiosk-needs-update-notice: amber warning + download link inside kiosk panel
- #scale-live-diag: device name, battery, live weight readout, reconnect info
- CSS cache bump ?v=20260506d
2026-05-06 14:07:29 +00:00
dadaloop82 e002cc4483 feat: nutrition analysis section + screensaver animated pie charts
app.js:
- _buildNutritionData(): category distribution, health/variety/freshness scores
- _renderNutritionSection(): animated 3D conic-gradient pie + legend + score bars
- _startInsightAlternation(): waste <-> nutrition fade-swap every hour
- _startScreensaverRotation(): facts and nutrition panel alternate every 5 min
- _renderScreensaverNutrition(): 3D animated pie + donut ring scores on screensaver
- _ssDonut(): CSS-only ring donut helper
- Removed two generic filler screensaver facts
- Cleaned up time-of-day screensaver facts (content-aware, no empty greetings)

index.html:
- Wrap waste/nutrition sections in #dashboard-insight-wrap
- Add #screensaver-nutrition slot in screensaver overlay
- Bump CSS cache ?v=20260506c

style.css:
- .ss-pie3d: 3D perspective + cubic-bezier spring + continuous slow spin
- .ss-donut-ring: CSS conic-gradient donut with bobbing animation
- .nutr-card, .nutr-pie-3d: dashboard nutrition card with 3D pie spin
- Score bars with fill transition
2026-05-06 14:00:13 +00:00
dadaloop82 115c966322 fix: scale dot contrast + kiosk scale config panel + download banner in kiosk
style.css:
- Scale connected dot: bright #4ade80 fill + white border + double shadow
  so it pops on the dark green header (was white on green = invisible)

index.html:
- Scale settings tab: add kiosk panel with 'Riconfigura bilancia BLE'
  button (hidden in browser, shown in kiosk mode)
- Wrap gateway download section and WebSocket URL section with IDs
  so JS can hide them in kiosk mode
- CSS cache bust ?v=20260506b

app.js:
- syncSettingsFromDB: in kiosk mode hide scale gateway download section,
  WebSocket URL section and test button; show kiosk BLE panel instead;
  auto-set URL to ws://localhost:8765
- Add _kioskReconfigureScale() helper that calls _kioskBridge.reconfigureScale()

KioskActivity.kt:
- Add reconfigureScale() @JavascriptInterface: stops GatewayService,
  clears saved scale device prefs, launches SetupActivity at step 4
- Import GatewayService
2026-05-06 13:44:50 +00:00
dadaloop82 f04e227cc0 fix: kiosk title center + location pref 2 uses + update confirm before download
app.js:
- _injectKioskOverlay: move kiosk-mode class assignment BEFORE the
  _kiosk_overlay existence guard — fixes race where Kotlin onPageFinished
  injects buttons during the await api() pause, then JS skips the class
- _PREF_LOC_NEEDED: 3 → 2 (remember use-location after 2 picks, not 3)

KioskActivity.kt:
- showNativeUpdateBanner: remove auto-start of triggerApkDownload;
  banner now shows with 'Scarica' button enabled, download only starts
  when user taps it (confirms before install)
2026-05-06 11:24:29 +00:00
dadaloop82 6d098a80a6 fix: scale auto-reconnect + reconfigure button in kiosk settings
GatewayService:
- onScanStopped() now calls scheduleReconnect() when not connected, so
  if the scale is off at startup the service keeps retrying every 8s
  instead of giving up after the first 20s scan window

SettingsActivity:
- Add 'Riconfigura bilancia' button (yellow outline) when a scale is
  already configured — clears saved device, stops the gateway service,
  and opens SetupActivity directly at step 4 (scale scan step)

SetupActivity:
- Accept 'start_step' intent extra to jump directly to a specific step
  (used by SettingsActivity reconfigure flow)
2026-05-06 11:18:38 +00:00
dadaloop82 8eba5c8573 fix: header title left-aligned by default, centered only in kiosk mode 2026-05-06 11:12:20 +00:00
dadaloop82 6f19d1bcd5 fix: screensaver watcher not activated when enabled from settings UI
initInactivityWatcher() was called once at startup and returned early if
screensaver was disabled at that moment. Enabling it later from the
settings panel had no effect until page reload.

- Make initInactivityWatcher() idempotent: attach DOM listeners only once
  (flag _inactivityListenersAttached), check screensaver_enabled dynamically
  inside each handler so disabling/enabling is reflected immediately
- Call initInactivityWatcher() at end of saveSettings() so the inactivity
  timer starts immediately when user enables screensaver
2026-05-06 05:35:37 +00:00
dadaloop82 ed89e74b94 fix: split Bimby/Cookeo appliances, add missing i18n keys, improve use_all dialog
- .env: split 'Bimby/Moulinex Cookeo' into 'Bimby' and 'Moulinex Cookeo'
- translations (it/en/de): add use_all_confirm_*, throw_all_confirm_*,
  confirm.cancel, confirm.proceed, location.dispensa/frigo/freezer
- app.js: when ANY opened package exists, always show disambiguation
  dialog ('solo questa confezione?' vs 'tutto?') instead of silently
  finishing one — was previously showing dialog only for 2+ opened packages
2026-05-06 05:22:49 +00:00
dadaloop82 f48fb02589 fix: center header title + bump to v1.7.3 for update detection
- CSS: header-title-wrap uses position:absolute with left:0/right:0
  + justify-content:center so title is truly centered regardless of
  button count on each side (kiosk has 2 left / 3 right)
- header-actions gets margin-left:auto to push right; both sides z-index:1
- Bump version 1.7.2 → 1.7.3 so already-open kiosk tabs will see
  the update badge once the new version is deployed to the server
- CSS cache bust: ?v=20260506a
2026-05-06 05:19:37 +00:00
dadaloop82 af9bae3093 fix: remove skeleton shimmer from dashboard stat cards 2026-05-06 05:15:44 +00:00
dadaloop82 521d8f8e47 fix: screensaver init timing + gemini key not wiped on settings save
- app.js: move initInactivityWatcher() inside syncSettingsFromDB().then()
  so it reads screensaver_enabled after server sync, not stale localStorage
- app.js: skip gemini_key/bring_password in save_settings POST when empty
  to avoid overwriting server .env with blank values
- api/index.php: add screensaver_enabled to getServerSettings() + saveSettings()
2026-05-06 05:14:10 +00:00
dadaloop82 14a7bbccbe fix: bust CSS cache (v20260505b) + bump webapp to v1.7.2
style.css was still served with ?v=20260421a so all CSS changes since
April 21 (scale indicator redesign, banner close button fix, etc.) were
invisible in the kiosk WebView — it used the cached old file.

Bumping manifest.json version 1.7.1→1.7.2 causes the auto-update
detector (_checkWebappUpdate) to fire on the kiosk: it compares the
loaded page version (1.7.1) with the server version (1.7.2), detects
a change, and shows the '⬆️ Aggiorna' badge so the user can reload.
2026-05-05 18:39:35 +00:00
dadaloop82 c7b04f410b fix: alert banner — 'Spiega' button and title layout
- explainBannerAnomaly: querySelector('#alert-banner .banner-detail')
  was wrong (class is 'alert-banner-detail'); function returned null → no-op.
  Fixed to getElementById('alert-banner-detail').
- alert-banner-inner: position close button absolutely (top:10px right:10px)
  so it is removed from the flex row and can never push the title-body to
  collapse or wrap under it. Inner gets padding-right:44px to reserve space.
- alert-banner-body: flex:1 1 0 + overflow:hidden for robust sizing
- alert-banner-title: word-break/overflow-wrap so very long product names
  wrap cleanly inside the body instead of overflowing
2026-05-05 18:25:16 +00:00
dadaloop82 754f13111f feat: kiosk setup improvements + webapp scale indicator fixes
kiosk setup wizard:
- Scale step: ask user to power on the scale before scanning (new
  'Accendi la bilancia' card with 'Bilancia accesa → Cerca' button)
- BLE scan: filter results to only show compatible scales (scaleScore>0)
  hiding clearly non-scale BLE devices from the list
- After device selection: run a live connection test — connect to the
  scale, display the live weight, ask 'Corrisponde al peso sulla bilancia?'
  with  Sì /  Riprova / Skip buttons before confirming the device

webapp:
- Scale indicator not live on first load: scaleInit() was firing before
  syncSettingsFromDB() resolved; fixed by chaining .then(scaleInit)
- Scale icon green-on-green: connected state dot changed from #22c55e
  (green, invisible on dark-green header) to white with green border+glow,
  visible on any background color
2026-05-05 18:11:51 +00:00
dadaloop82 7ea5505a0d fix: scale indicator, logo crop, gateway LAN IP, setup spacing
webapp:
- Scale indicator: replace plain green dot with ⚖️ emoji + colored
  status badge (green/amber/grey/red); icon fades out when disconnected;
  tap shows a toast with device name + battery level
- Logo images: crop excess transparent padding from logo.png and
  logo_icon.png so content fills the frame at small display sizes
- style.css: reworked .scale-status-indicator CSS for emoji+badge

kiosk:
- SetupActivity: use device's real LAN IP for scale_gateway_url
  (was hardcoded 127.0.0.1 — only worked if server and kiosk run on
  the same machine); added getDeviceLanIp() helper (prefers wlan/eth)
- activity_setup.xml: reduce welcome step padding/margins so step 1
  fits on screen without scrolling; text sizes slightly reduced
- activity_setup.xml: fix feature bullet 'Bilancia Bluetooth via
  Gateway app' → 'Bilancia BLE integrata (nessuna app esterna)'
- strings.xml (en + it): rewrite all wizard_gateway_* strings to
  reflect integrated BLE service instead of external gateway APK
- ic_logo.png: regenerated at all densities from cropped source
2026-05-05 17:47:54 +00:00
dadaloop82 a5094920bf kiosk: remove all external gateway app references + update docs
- SettingsActivity: replace GATEWAY_PACKAGE / PackageManager check with
  GatewayService status; show BLE device name + live :8765 probe;
  buttons now restart GatewayService or redirect to setup wizard
- activity_settings.xml: rename section label to 'BILANCIA SMART',
  update button text to '⚙️ Configura bilancia'
- evershelf-scale-gateway/README.md: add DEPRECATED notice (gateway is
  now integrated into kiosk v1.6.0+, this app is no longer maintained)
- evershelf-kiosk/README.md: full rewrite — reflects v1.6.0, integrated
  BLE gateway, 6-step wizard, permissions table, protocol reference
- README.md: update kiosk features (remove gateway APK install/launch,
  add integrated BLE service), update scale section, update architecture,
  add kiosk v1.6.0 entry in Recent Updates
2026-05-05 17:31:14 +00:00
dadaloop82 9cb29de1f0 kiosk: integrate BLE scale gateway + fix logo/branding
- Kiosk v1.6.0 (versionCode 10)
  - Integrate BLE scale gateway directly into kiosk app (no external app needed)
    - New scale/ package: BleScaleManager, GatewayWebSocketServer, ScaleProtocol, GatewayService
    - GatewayService: foreground service, runs BLE scan + WebSocket :8765 server
    - Auto-reconnect on BLE disconnect; protocol compatible with old gateway app
  - Setup step 4: replace gateway install flow with BLE device scan + selection (mandatory)
  - Permissions: added BLUETOOTH_SCAN, BLUETOOTH_CONNECT, ACCESS_FINE_LOCATION (pre-S),
    FOREGROUND_SERVICE, FOREGROUND_SERVICE_CONNECTED_DEVICE
  - KioskActivity: replace launchGatewayInBackground() with startGatewayService()
  - checkForUpdates: remove gateway APK check (gateway is now internal)
  - Remove GATEWAY_PACKAGE / GATEWAY_DOWNLOAD_URL constants

- Logo / branding
  - logo.png + logo_icon.png: transparent background (no more black)
  - ic_logo.png regenerated in all densities
  - Removed house emoji (🏠) from web UI: favicon, bottom nav, setup wizard header
  - Removed 🏠 prefix from all translations (it/en/de) and manifest
  - Setup wizard: logo shown in language + welcome steps
  - Setup wizard: footer with credits ('Creato da Stimpfl Daniel • Open Source')
  - CSS: .nav-logo-icon for bottom nav logo sizing

- Scale Gateway v2.1.1 (versionCode 8)
  - Fix false update notification: replace == comparison with proper semverNewer()
    (was reporting 'update available' whenever tag != current, e.g. v2.1.0 != 2.1.0)
2026-05-05 17:24:24 +00:00
dadaloop82 8ee6fe8770 kiosk: gateway auto-launch, update auto-download, gateway setup UX
- KioskActivity: move launchGatewayInBackground() BEFORE enableKioskLock() so
  Android's lock-task restriction does not block starting the gateway Activity
- KioskActivity: webView.clearCache(true) before loadUrl — no caching
- KioskActivity: checkForUpdates() uses proper semver > comparison (not !=)
  to avoid false-positive 'update available' when already up-to-date
- KioskActivity: showNativeUpdateBanner() removed 30s auto-hide, now auto-
  triggers download immediately when update detected
- SetupActivity: onResume() re-checks gateway status when returning from gateway
  config (user opens gateway, configures it, presses back → wizard refreshes)
- SetupActivity: checkGatewayStatus() probes TCP 127.0.0.1:8765 to show whether
  gateway is actually running, with clear 'not running' warning to configure first
- SettingsActivity: same TCP probe for live gateway status in settings screen
- build.gradle.kts: versionCode 9, versionName 1.5.3
2026-05-05 16:48:32 +00:00
dadaloop82 30aa2db0b9 branding: add EverShelf logo to kiosk splash + web header/preloader
- assets/img/logo/logo.png: trimmed full logo (icon + text, transparent bg)
- assets/img/logo/logo_icon.png: icon-only crop (no text, for header)
- drawable-*/ic_logo.png: multi-density PNGs for Android splash (mdpi→xxxhdpi)
- activity_kiosk.xml: replace ic_launcher_foreground with ic_logo at 260dp,
  remove redundant 'EverShelf' text row (already in logo image)
- index.html: add logo_icon.png in header title, logo.png in preloader
- style.css: add .app-preloader-logo and .header-logo-icon rules
2026-05-05 16:37:57 +00:00
dadaloop82 b8d91c0089 kiosk: add missing Toast import in SetupActivity 2026-05-05 16:09:09 +00:00
dadaloop82 2ebf79d394 kiosk: fix strings.xml apostrophe syntax (&#39; -> \') 2026-05-05 16:05:54 +00:00
dadaloop82 6500d22242 kiosk: fix install dialog + screensaver always-on
Fallback install (Intent.ACTION_VIEW):
- Remove FLAG_ACTIVITY_NEW_TASK: it caused startActivityForResult to return
  RESULT_CANCELED immediately, making the system installer dialog disappear in ~1s
- After fallback returns with app not installed: show '🔄 Riprova installazione'
  button that calls tryFallbackInstall() directly (skips PackageInstaller which
  is known to give STATUS=1 on this device)

Screensaver:
- KioskActivity.applyScreensaverFlag(): always add FLAG_KEEP_SCREEN_ON, never
  clear it — screen must ALWAYS stay on in kiosk mode
- The 'salvaschermo' toggle controls the in-app JS clock overlay (webapp setting),
  NOT the Android screen timeout
- finishSetup(): always push screensaver_enabled to webapp API (not just when scale
  is configured)
- SettingsActivity save: remove FLAG_KEEP_SCREEN_ON conditional; push
  screensaver_enabled to server API on save
- Update setup wizard description + strings to clarify in-app overlay vs screen off

Bump version to 1.5.2 (versionCode 8)
2026-05-05 16:01:47 +00:00
dadaloop82 84d2ff0264 kiosk: improve wizard UX + gateway configurability
- Wizard step 4 (scale): skip question if scale already configured (KEY_HAS_SCALE=true), show gateway status directly
- Add '⚙️ Apri Gateway per configurarlo' button in setup wizard after gateway is installed
- Add same button in SettingsActivity SMART SCALE section (visible only when installed)
- Fix btnRunWizard in SettingsActivity: immediately launches SetupActivity instead of just showing a toast
- Bump version to 1.5.1 (versionCode 7)
2026-05-05 06:09:48 +00:00
dadaloop82 b2a334340b fix(kiosk): warn user to press 'Done' not 'Open' after gateway install
- Before launching system installer (ACTION_VIEW fallback), show a
  non-cancellable dialog warning: press Fine, NOT Apri
- After installer returns, force SetupActivity back to foreground in case
  user pressed Open anyway (FLAG_ACTIVITY_REORDER_TO_FRONT)
2026-05-05 06:01:53 +00:00
dadaloop82 0f0ce684f1 fix(kiosk): fallback Intent.ACTION_VIEW when PackageInstaller STATUS=1 + fix self-update URL
- SetupActivity: catch STATUS_FAILURE=1 separately and immediately retry with
  Intent.ACTION_VIEW (system installer dialog) instead of showing a dead error.
  STATUS=1 is a generic PackageInstaller failure that can happen on many
  Android 14 devices even with a valid APK, but the system installer handles it.
- SetupActivity: remove misleading 'incompatibile' hint for status=1 (was wrong;
  STATUS_FAILURE_INCOMPATIBLE = 7, not 1).
- SetupActivity: deduplicate buildDeviceLabel() to shared private method
- KioskActivity: fix KIOSK_DOWNLOAD_URL to point to kiosk-latest release
  (was pointing to 'latest' which only has the gateway APK, so self-update
  was silently broken).
- Bump version 1.4.0 -> 1.5.0 (versionCode 5 -> 6)
2026-05-05 05:50:22 +00:00
dadaloop82 abeb87c536 fix(kiosk): fix APK install failure — session lifecycle, error details, issue reporting
- KioskActivity: remove .use{} on PackageInstaller session to prevent premature
  session close causing STATUS_FAILURE=1; align with SetupActivity pattern
- SetupActivity: show full diagnostic info (status code + human-readable hint,
  device, Android version) in the UI card instead of just 'status=1'
- SetupActivity: use Build.PRODUCT/BOARD fallback when MANUFACTURER='unknown'
- ErrorReporter: add forceReport param to bypass in-session dedup for retries
- ErrorReporter: include Android SDK version in deviceInfo; fallback for
  'unknown' MANUFACTURER/MODEL using PRODUCT/HARDWARE/BOARD
2026-05-05 05:32:31 +00:00
dadaloop82 fc47cd8c27 fix: allow free-form quantity input for ml/g sub-units (no step constraint) 2026-05-05 05:19:51 +00:00
dadaloop82 1e8c299052 docs: update wiki link in README to official GitHub wiki 2026-05-04 20:09:37 +00:00
dadaloop82 36d2328eb4 docs: add live demo banner to README + complete wiki (9 pages)
README:
- Added prominent live demo banner at the top with links to
  https://evershelfproject.dadaloop.it/demo and project website

Wiki (docs/wiki/):
- Home.md         — overview, table of contents, what's new
- Installation.md — Docker, Apache, Nginx, HTTPS, cron, backup
- Configuration.md — full .env reference, settings UI, rate limits
- Features.md     — complete feature documentation
- API-Reference.md — all REST endpoints with params/responses
- Android-Kiosk.md — setup wizard, permissions, troubleshooting
- Scale-Gateway.md — BLE protocol, setup, troubleshooting
- Translations.md  — how to add/edit language files
- Contributing.md  — dev workflow, branch strategy, CI, code style
- FAQ.md           — common issues and solutions
2026-05-04 20:01:45 +00:00
dadaloop82 d02e48543f chore: release v1.7.1
- 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()
2026-05-04 19:50:39 +00:00
dadaloop82 74c4f8bd78 fix(webapp): remove redundant closeModal() before destructive confirm 2026-05-04 18:43:48 +00:00
dadaloop82 2e46090adc fix(webapp): confirmation dialog + undo button visibility
- Add _showDestructiveConfirm() helper: shows modal with 5-second
  auto-confirm countdown bar; user can confirm early or cancel
- throwAll(): now shows confirmation before discarding all stock
- submitUseAll(): same confirmation before marking all as used
- undoTransactionEntry(): replace native confirm() with modal
- Rename core logic to _doSubmitUseAll() / _doUndoTransaction()
- btn-log-undo: more visible (red tint + larger font) so user can
  easily undo accidental operations from the history log
- Bump app.js version to v=20260505a
2026-05-04 18:30:30 +00:00
dadaloop82 e4869c4308 fix(kiosk): gateway install hardening + diagnostic dialog on failure
- installApk(): add runtime canRequestPackageInstalls() check with user dialog
  (permission may have been revoked or not active even if declared in manifest)
- STATUS_FAILURE else branch: show AlertDialog with full diagnostics on screen
  (status code, message, APK size, Android version, device model) so the
  problem is visible even when the server error report fails to deliver
- Dialog has Riprova button (retries installWithPackageInstaller immediately)
  and Salta button (skips to gateway status check)
- INSTALL_PERM_REQUEST onActivityResult: resume from installApk() if a local
  APK file is already present, not just from triggerApkDownload()
- ErrorReporter context enriched with device model string
2026-05-04 18:24:56 +00:00
dadaloop82 6d13b895ea fix(kiosk): gateway install STATUS_FAILURE root cause
Two bugs caused the gateway APK install to always fail with status=1:

1. setAppPackageName() removed from SessionParams
   This optional call forces the installer to verify the package name
   against the APK's manifest. On some OEM/Android versions this
   comparison fails even when the name is correct, returning the generic
   STATUS_FAILURE (1) with no EXTRA_STATUS_MESSAGE. Removing it lets
   the installer proceed without the extra check.

2. BroadcastReceiver was unregistered on STATUS_PENDING_USER_ACTION
   On Android 11+ the final install result (STATUS_SUCCESS/STATUS_FAILURE)
   arrives as a SECOND broadcast AFTER the user confirms the dialog.
   The receiver was being unregistered immediately on the first broadcast
   (PENDING_USER_ACTION), so the final result was never received.
   Fix: only unregister on terminal statuses (SUCCESS, FAILURE, ABORTED).

Additional improvements:
- STATUS_FAILURE_ABORTED (-1) handled explicitly: resets UI without
  showing an error (user just pressed back on the confirmation dialog)
- session.abandon() called on exception instead of letting .use{} close
- ErrorReporter now includes apk_kb and android API level in context
- onActivityResult(INSTALL_CONFIRM_REQUEST) no longer sets success/failure
  UI (the BroadcastReceiver is responsible for the final result)
2026-05-04 18:07:35 +00:00