- 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()
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.
- 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
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
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
- 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
- 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