From 8360f5a0a0b33c000c75914b13d7b6570b2b1241 Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Sun, 17 May 2026 15:40:01 +0000 Subject: [PATCH] feat(kiosk-wizard): step Features con screensaver, prezzi, piano pasti, zero-waste tips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 5 del wizard ora mostra 4 toggle (pre-compilati se già configurati): - Salvaschermo orologio (screensaver_enabled) - Prezzi lista spesa (price_enabled) - Piano pasti (meal_plan_enabled) - Suggerimenti zero-waste durante cottura (zerowaste_tips_enabled) Solo i toggle NON ancora impostati in prefs partono da false (fresh install). Tutti e 4 vengono salvati in SharedPreferences e inviati al server via save_settings al completamento del wizard. PHP/JS: zerowaste_tips_enabled aggiunto come impostazione server-side (ZEROWASTE_TIPS_ENABLED in .env), sincronizzata nel WebView via _applySyncedSettings() al caricamento. --- api/index.php | 2 + assets/js/app.js | 3 +- .../dadaloop/evershelf/kiosk/SetupActivity.kt | 62 +++++--- .../src/main/res/layout/activity_setup.xml | 138 +++++++++++++++--- .../app/src/main/res/values/strings.xml | 21 ++- 5 files changed, 184 insertions(+), 42 deletions(-) diff --git a/api/index.php b/api/index.php index 81bcb91..77c6455 100644 --- a/api/index.php +++ b/api/index.php @@ -2652,6 +2652,7 @@ function getServerSettings(): void { 'meal_plan_enabled' => env('MEAL_PLAN_ENABLED', 'false') === 'true', 'screensaver_enabled' => env('SCREENSAVER_ENABLED', 'false') === 'true', 'screensaver_timeout' => (int)env('SCREENSAVER_TIMEOUT', '5'), + 'zerowaste_tips_enabled' => env('ZEROWASTE_TIPS_ENABLED', 'false') === 'true', 'price_enabled' => env('PRICE_ENABLED', 'false') === 'true', 'price_country' => env('PRICE_COUNTRY', 'Italia'), 'price_currency' => env('PRICE_CURRENCY', 'EUR'), @@ -2709,6 +2710,7 @@ function saveSettings(): void { 'meal_plan_enabled' => 'MEAL_PLAN_ENABLED', 'screensaver_enabled' => 'SCREENSAVER_ENABLED', 'price_enabled' => 'PRICE_ENABLED', + 'zerowaste_tips_enabled' => 'ZEROWASTE_TIPS_ENABLED', ]; // Integer keys $intMap = [ diff --git a/assets/js/app.js b/assets/js/app.js index c00ea18..23d1a23 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -2185,7 +2185,8 @@ function _applySyncedSettings(serverSettings) { 'tts_method','tts_auth_type','tts_content_type','tts_payload_key', 'tts_engine','tts_rate','tts_pitch','tts_auth_header_name','tts_auth_header_value','tts_extra_fields', 'screensaver_enabled','screensaver_timeout', - 'price_enabled','price_country','price_currency','price_update_months']; + 'price_enabled','price_country','price_currency','price_update_months', + 'zerowaste_tips_enabled']; let changed = false; for (const key of serverKeys) { if (serverSettings[key] !== undefined && serverSettings[key] !== null && serverSettings[key] !== '') { diff --git a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt index 1f1825f..8001cc8 100644 --- a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt +++ b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt @@ -110,6 +110,9 @@ class SetupActivity : AppCompatActivity() { // Screensaver step private lateinit var setupSwitchScreensaver: SwitchMaterial + private lateinit var setupSwitchPrices: SwitchMaterial + private lateinit var setupSwitchMealPlan: SwitchMaterial + private lateinit var setupSwitchZeroWaste: SwitchMaterial // Done step private lateinit var summaryText: TextView @@ -128,6 +131,9 @@ class SetupActivity : AppCompatActivity() { private const val KEY_HAS_SCALE = "has_scale" private const val KEY_LANGUAGE = "kiosk_language" private const val KEY_SCREENSAVER = "screensaver_enabled" + private const val KEY_PRICE_ENABLED = "price_enabled" + private const val KEY_MEAL_PLAN = "meal_plan_enabled" + private const val KEY_ZEROWASTE_TIPS = "zerowaste_tips_enabled" private const val PERMISSION_REQUEST_CODE = 2004 private const val BLE_PERMISSION_REQUEST = 2006 @@ -238,10 +244,17 @@ class SetupActivity : AppCompatActivity() { tvTestWeight = findViewById(R.id.tvTestWeight) testWeightBox = findViewById(R.id.testWeightBox) - // Screensaver step + // Features step — bind all four toggles setupSwitchScreensaver = findViewById(R.id.setupSwitchScreensaver) - // Pre-fill saved screensaver pref - setupSwitchScreensaver.isChecked = prefs.getBoolean(KEY_SCREENSAVER, false) + setupSwitchPrices = findViewById(R.id.setupSwitchPrices) + setupSwitchMealPlan = findViewById(R.id.setupSwitchMealPlan) + setupSwitchZeroWaste = findViewById(R.id.setupSwitchZeroWaste) + // Pre-fill from saved prefs only if each key was previously configured + // ("se non sono impostati, chiedi!" — fresh install → all start at false) + setupSwitchScreensaver.isChecked = if (prefs.contains(KEY_SCREENSAVER)) prefs.getBoolean(KEY_SCREENSAVER, false) else false + setupSwitchPrices.isChecked = if (prefs.contains(KEY_PRICE_ENABLED)) prefs.getBoolean(KEY_PRICE_ENABLED, false) else false + setupSwitchMealPlan.isChecked = if (prefs.contains(KEY_MEAL_PLAN)) prefs.getBoolean(KEY_MEAL_PLAN, false) else false + setupSwitchZeroWaste.isChecked = if (prefs.contains(KEY_ZEROWASTE_TIPS)) prefs.getBoolean(KEY_ZEROWASTE_TIPS, false) else false // Done step summaryText = findViewById(R.id.setupSummaryText) @@ -381,10 +394,15 @@ class SetupActivity : AppCompatActivity() { findViewById(R.id.btnScaleNext).isEnabled = true } - // ── Screensaver ─────────────────────────────────────────────────── + // ── Features step (screensaver / prices / meal plan / zero-waste) ──── findViewById(R.id.btnScreensaverBack).setOnClickListener { showStep(4) } findViewById(R.id.btnScreensaverNext).setOnClickListener { - prefs.edit().putBoolean(KEY_SCREENSAVER, setupSwitchScreensaver.isChecked).apply() + prefs.edit() + .putBoolean(KEY_SCREENSAVER, setupSwitchScreensaver.isChecked) + .putBoolean(KEY_PRICE_ENABLED, setupSwitchPrices.isChecked) + .putBoolean(KEY_MEAL_PLAN, setupSwitchMealPlan.isChecked) + .putBoolean(KEY_ZEROWASTE_TIPS, setupSwitchZeroWaste.isChecked) + .apply() showStep(6) } @@ -971,13 +989,16 @@ class SetupActivity : AppCompatActivity() { // ── Summary / Finish ───────────────────────────────────────────────── private fun buildSummary() { - val url = prefs.getString(KEY_URL, "") ?: "" - val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false) - val screensOn = setupSwitchScreensaver.isChecked - val scaleName = bleManager?.getSavedDeviceName() - val scaleOk = hasScale && scaleName != null - val lang = prefs.getString(KEY_LANGUAGE, "it") ?: "it" - val langLabel = when (lang) { "en" -> "English 🇬🇧"; "de" -> "Deutsch 🇩🇪"; else -> "Italiano 🇮🇹" } + val url = prefs.getString(KEY_URL, "") ?: "" + val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false) + val screensOn = setupSwitchScreensaver.isChecked + val pricesOn = setupSwitchPrices.isChecked + val mealPlanOn = setupSwitchMealPlan.isChecked + val zeroWasteOn = setupSwitchZeroWaste.isChecked + val scaleName = bleManager?.getSavedDeviceName() + val scaleOk = hasScale && scaleName != null + val lang = prefs.getString(KEY_LANGUAGE, "it") ?: "it" + val langLabel = when (lang) { "en" -> "English 🇬🇧"; "de" -> "Deutsch 🇩🇪"; else -> "Italiano 🇮🇹" } val sb = StringBuilder() sb.appendLine("🌐 ${getString(R.string.summary_lang)}: $langLabel") if (url.isNotEmpty()) sb.appendLine("🖥️ Server: $url") @@ -986,7 +1007,10 @@ class SetupActivity : AppCompatActivity() { hasScale -> "⚠️ Bilancia: da configurare" else -> "⏭ ${getString(R.string.summary_scale_skip)}" }) - sb.appendLine(if (screensOn) "🌙 ${getString(R.string.summary_screensaver_on)}" else "💡 ${getString(R.string.summary_screensaver_off)}") + sb.appendLine(if (screensOn) getString(R.string.summary_screensaver_on) else getString(R.string.summary_screensaver_off)) + if (pricesOn) sb.appendLine(getString(R.string.summary_prices_on)) + if (mealPlanOn) sb.appendLine(getString(R.string.summary_mealplan_on)) + if (zeroWasteOn) sb.appendLine(getString(R.string.summary_zerowaste_on)) summaryText.text = sb.toString().trimEnd() } @@ -994,16 +1018,20 @@ class SetupActivity : AppCompatActivity() { prefs.edit().putBoolean(KEY_SETUP_COMPLETE, true).apply() val baseUrl = (prefs.getString(KEY_URL, "") ?: "").trimEnd('/') if (baseUrl.isNotEmpty()) { - val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false) && (bleManager?.getSavedDeviceAddress() != null) - val screensaver = prefs.getBoolean(KEY_SCREENSAVER, false) + val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false) && (bleManager?.getSavedDeviceAddress() != null) + val screensaver = prefs.getBoolean(KEY_SCREENSAVER, false) + val priceEnabled = prefs.getBoolean(KEY_PRICE_ENABLED, false) + val mealPlan = prefs.getBoolean(KEY_MEAL_PLAN, false) + val zeroWaste = prefs.getBoolean(KEY_ZEROWASTE_TIPS, false) Thread { try { val url = "$baseUrl/api/index.php?action=save_settings" val body = buildString { append("{\"screensaver_enabled\":$screensaver") + append(",\"price_enabled\":$priceEnabled") + append(",\"meal_plan_enabled\":$mealPlan") + append(",\"zerowaste_tips_enabled\":$zeroWaste") if (hasScale) { - // Use the tablet's actual LAN IP so the EverShelf server - // (potentially on a different machine) can reach the gateway. val lanIp = getDeviceLanIp() ?: "127.0.0.1" append(",\"scale_enabled\":true,\"scale_gateway_url\":\"ws://$lanIp:8765\"") } diff --git a/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml b/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml index 2aa5b73..e16176a 100644 --- a/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml +++ b/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml @@ -1050,7 +1050,7 @@ + android:layout_marginBottom="20dp" /> - + - + android:layout_marginBottom="10dp"> - - + android:layout_marginBottom="3dp" /> + android:textSize="12sp" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + Error reporting is active — install failures will be sent to GitHub Issues automatically. Server not reachable ⚠️ Install errors won\'t reach GitHub Issues. Check the URL entered in step 2. - + + Funzionalità + Attiva le funzioni che vuoi usare. Puoi sempre cambiarle in seguito dalle impostazioni del server. Salvaschermo in-app Shows a clock with useful facts after 5 minutes of inactivity. Off by default (screen stays always on). - Abilita salvaschermo orologio - Mostra l\'overlay orologio dopo 5 min. Lo schermo resta sempre acceso. + Salvaschermo orologio + Mostra l\'overlay orologio dopo 5 min di inattività. + Prezzi lista spesa + Stima automatica del costo di ogni articolo in lista tramite AI. + Piano pasti + Pianifica i pasti della settimana suggerendo ricette basate sulla dispensa. + Suggerimenti zero-waste + Durante la cottura mostra consigli per riutilizzare scarti (bucce, acqua di cottura, ecc.). Language Scale: not configured - Screensaver: enabled - Screen always on (screensaver disabled) + Screensaver: abilitato + Screensaver: disabilitato + Prezzi lista spesa: abilitati + Piano pasti: abilitato + Suggerimenti zero-waste: abilitati