- 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
- 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
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)
- 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)
- 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)
- 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)
- 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
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
- 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
- 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
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)
SetupActivity was sending type 'install-failure' (hyphen) but the PHP
version-guard bypass list only checked for 'install_failure' (underscore).
Result: if the kiosk was not on the latest released version the error was
silently discarded and no GitHub issue was created.
Fix:
- SetupActivity: change type to 'install_failure' (underscore, consistent
with KioskActivity which already used the correct name)
- api/index.php: add 'install-failure' (hyphen) to the bypass list as
defensive fallback so old APK builds already in the field are covered too
ErrorReporter:
- Init ErrorReporter at Setup onCreate using any previously saved URL
(before the fix, init() was only called at step 3, so install errors
happening in step 4 were silently dropped)
- Add ErrorReporter.reportMessage() call in the STATUS_FAILURE else branch
of installWithPackageInstaller (was showing error UI but sending nothing)
Gateway pre-configuration:
- finishSetup() now detects has_scale=true + gateway installed
- If so, POSTs scale_enabled=true + scale_gateway_url=ws://127.0.0.1:8765
to the EverShelf server's save_settings API endpoint
- This means the webapp works with the scale out-of-the-box after setup
without the user having to go into web Settings and configure it manually
Permissions step:
- Add btnGrantPerms as class field (was only inline findViewById)
- Extract onPermissionsGranted() helper: transforms button to green '✅ Permessi
concessi — Continua →' and sets click listener to showStep(3)
instead of calling onPermissionsGranted() which advances to step 3 (Server)
- Remove the 600ms auto-advance; user controls when to proceed
- Add setup_perms_granted_next string in EN/IT/DE
Network discovery — wrong subnet fix:
- Skip virtual/VPN/cellular interfaces: tun, ppp, rmnet, pdp, ccmni, dummy, sit,
gre, v4-, v6-, p2p, ham, nordlynx prefixes
- Also skip intf.isVirtual interfaces
- Sort: wlan*/eth* interfaces first (highest priority), others after
- Show detected subnet(s) in UI immediately before scan starts
Problems fixed:
- f.get() sequential collection blocked on timed-out futures in submission order
→ replaced with ExecutorCompletionService: results collected as soon as ready
- WifiManager.getConnectionInfo() deprecated on Android 10+, could return IP=0
→ replaced with NetworkInterface.getNetworkInterfaces() for subnet detection
- No real-time feedback: status stuck on 'Scanning…' throughout
→ UI updated every ~120ms showing current IP:port (n/total)
- TCP socket pre-check (600ms) before HTTP probe: filters unreachable hosts instantly
→ reduces scan time from minutes to seconds on typical /24 networks
- executor.shutdownNow() cancels remaining tasks the moment server is found
- 60-thread pool instead of 40 for faster parallel scanning
- Remove unused WifiManager import
- Replace checkbox-label with toggle-row pattern matching other toggles
- Add missing <span class="toggle-slider"></span> inside toggle-switch
- Add data-i18n attributes to card title and hint
- Add screensaver.card_title / card_hint translations in all 3 locales
feat(demo): full demo mode implementation
- _applyDemoModeUI(): set _geminiAvailable=true + call _updateGeminiButtonState()
- api(): no-op all bring_add/bring_remove/bring_set_spec calls in demo mode
- api(): return in-memory shoppingItems for bring_list in demo mode
- loadShoppingList(): show placeholder list in demo mode, skip all Bring! calls
fix(shopping): graceful Bring! missing credentials handling
- Show friendly message with link to settings instead of raw PHP error
- Add shopping.bring_not_configured i18n key in IT/EN/DE
Bump app.js cache buster to v=20260504b