From 4897da571d6c4c8a558ad1d47ac52ba278eaa40c Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Sun, 3 May 2026 18:31:22 +0000 Subject: [PATCH] feat(kiosk): ask if scale is present; check+update gateway in wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wizard step 3 — 'Do you have a Bluetooth smart scale?': - New question card with two buttons shown first: ✅ Yes → reveal gateway status card + bottom nav buttons ➡️ No → save KEY_HAS_SCALE=false, skip to web view - KEY_HAS_SCALE pref controls whether the gateway is auto-launched both after wizard completion and on every subsequent app start - checkGatewayStatus(): uses string resources (multilingual) - checkGatewayUpdate(): fetches GitHub release, compares version; if gateway needs an update shows '📥 Update Scale Gateway' button that triggers triggerApkDownload() (full PackageInstaller flow) - onResume step-3 re-check only fires when status card is visible (i.e. user already answered 'Yes') — handles return from install Multi-language: strings.xml added for EN (default), IT, DE strings: wizard_step3_question/yes/no, wizard_gateway_installed/ not_installed/checking/up_to_date/update_available/update_detail, btn_back/launch/launch_no_scale/download_gateway/update_gateway --- .../dadaloop/evershelf/kiosk/KioskActivity.kt | 125 +++++++++++++++--- .../src/main/res/layout/activity_kiosk.xml | 74 +++++++++-- .../app/src/main/res/values-de/strings.xml | 28 ++++ .../app/src/main/res/values-it/strings.xml | 28 ++++ .../app/src/main/res/values/strings.xml | 24 ++++ 5 files changed, 246 insertions(+), 33 deletions(-) create mode 100644 evershelf-kiosk/app/src/main/res/values-de/strings.xml create mode 100644 evershelf-kiosk/app/src/main/res/values-it/strings.xml diff --git a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt index 5e73814..88124a0 100644 --- a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt +++ b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt @@ -77,6 +77,8 @@ class KioskActivity : AppCompatActivity() { private lateinit var scaleStatusIcon: TextView private lateinit var scaleStatusText: TextView private lateinit var scaleStatusDetail: TextView + private lateinit var scaleQuestionLayout: LinearLayout + private lateinit var step3BottomButtons: LinearLayout // Update banner (native, shown at the top over the WebView) private lateinit var updateBanner: LinearLayout private lateinit var tvUpdateMessage: TextView @@ -106,6 +108,7 @@ class KioskActivity : AppCompatActivity() { private const val PREFS_NAME = "evershelf_kiosk" private const val KEY_URL = "evershelf_url" private const val KEY_SETUP_COMPLETE = "setup_complete" + private const val KEY_HAS_SCALE = "has_scale" private const val GATEWAY_PACKAGE = "it.dadaloop.evershelf.scalegate" private const val GATEWAY_DOWNLOAD_URL = "https://github.com/dadaloop82/EverShelf/releases/latest/download/evershelf-scale-gateway.apk" private const val KIOSK_DOWNLOAD_URL = "https://github.com/dadaloop82/EverShelf/releases/latest/download/evershelf-kiosk.apk" @@ -166,6 +169,8 @@ class KioskActivity : AppCompatActivity() { scaleStatusIcon = findViewById(R.id.scaleStatusIcon) scaleStatusText = findViewById(R.id.scaleStatusText) scaleStatusDetail = findViewById(R.id.scaleStatusDetail) + scaleQuestionLayout = findViewById(R.id.scaleQuestionLayout) + step3BottomButtons = findViewById(R.id.step3BottomButtons) // Update banner updateBanner = findViewById(R.id.updateBanner) @@ -204,10 +209,21 @@ class KioskActivity : AppCompatActivity() { goToStep(2) } findViewById(R.id.btnFinish).setOnClickListener { + prefs.edit().putBoolean(KEY_HAS_SCALE, true).apply() launchGatewayInBackground() finishWizard() } - findViewById(R.id.btnSkipScale).setOnClickListener { + // "Yes" → reveal gateway status and proceed flow + findViewById(R.id.btnScaleYes).setOnClickListener { + scaleQuestionLayout.visibility = View.GONE + val statusCard = findViewById(R.id.scaleStatusCard) + statusCard.visibility = View.VISIBLE + step3BottomButtons.visibility = View.VISIBLE + checkGatewayStatus() + } + // "No" → save pref and skip to web view + findViewById(R.id.btnScaleNo).setOnClickListener { + prefs.edit().putBoolean(KEY_HAS_SCALE, false).apply() finishWizard() } @@ -320,7 +336,12 @@ class KioskActivity : AppCompatActivity() { updateStepIndicator() if (step == 3) { - checkGatewayStatus() + // Reset to question state every time step 3 is entered + scaleQuestionLayout.visibility = View.VISIBLE + val statusCard = findViewById(R.id.scaleStatusCard) + statusCard.visibility = View.GONE + step3BottomButtons.visibility = View.GONE + findViewById(R.id.btnSkipScale).visibility = View.GONE } } @@ -376,6 +397,7 @@ class KioskActivity : AppCompatActivity() { } private fun launchGatewayInBackground() { + if (!prefs.getBoolean(KEY_HAS_SCALE, false)) return if (!isGatewayInstalled()) return val launchIntent = packageManager.getLaunchIntentForPackage(GATEWAY_PACKAGE) ?: return launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -389,32 +411,93 @@ class KioskActivity : AppCompatActivity() { private fun checkGatewayStatus() { if (isGatewayInstalled()) { - scaleStatusIcon.text = "✅" - scaleStatusText.text = "Scale Gateway is installed" - scaleStatusDetail.text = "It will be launched in the background when you proceed" - scaleStatusDetail.setTextColor(0xFF34d399.toInt()) + scaleStatusIcon.text = "\u2705" + scaleStatusText.text = getString(R.string.wizard_gateway_installed) + scaleStatusDetail.text = getString(R.string.wizard_gateway_checking) + scaleStatusDetail.setTextColor(0xFF94a3b8.toInt()) findViewById(R.id.btnSkipScale).visibility = View.GONE - findViewById(R.id.btnFinish).text = "🚀 Launch EverShelf" + findViewById(R.id.btnFinish).text = getString(R.string.btn_launch) + // Check async if a newer version is available + checkGatewayUpdate() } else { - scaleStatusIcon.text = "📥" - scaleStatusText.text = "Scale Gateway not installed" - scaleStatusDetail.text = "Install the Scale Gateway app to use a Bluetooth scale" + scaleStatusIcon.text = "\uD83D\uDCE5" + scaleStatusText.text = getString(R.string.wizard_gateway_not_installed) + scaleStatusDetail.text = getString(R.string.wizard_gateway_not_installed_detail) scaleStatusDetail.setTextColor(0xFFfbbf24.toInt()) - - findViewById(R.id.btnFinish).text = "🚀 Launch without scale" - + findViewById(R.id.btnFinish).text = getString(R.string.btn_launch_no_scale) findViewById(R.id.btnSkipScale).apply { - text = "📥 Download Scale Gateway" - setTextColor(0xFF7c3aed.toInt()) + text = getString(R.string.btn_download_gateway) + setTextColor(0xFFa78bfa.toInt()) visibility = View.VISIBLE - setOnClickListener { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(GATEWAY_DOWNLOAD_URL)) - startActivity(intent) - } + setOnClickListener { triggerApkDownload(GATEWAY_DOWNLOAD_URL) } } } } + /** Fetches the latest GitHub release and, if the gateway has an available update, + * shows the update button in the wizard status card. */ + private fun checkGatewayUpdate() { + val currentVersion = try { + packageManager.getPackageInfo(GATEWAY_PACKAGE, 0).versionName ?: return + } catch (_: Exception) { return } + + Thread { + try { + val conn = URL(GITHUB_RELEASES_API).openConnection() as java.net.HttpURLConnection + conn.setRequestProperty("Accept", "application/vnd.github+json") + conn.connectTimeout = 5000 + conn.readTimeout = 5000 + val json = JSONObject(conn.inputStream.bufferedReader().readText()) + conn.disconnect() + + val latestTag = json.optString("tag_name", "") + if (latestTag.isEmpty()) { showGatewayUpToDate(); return@Thread } + + val isSemver = latestTag.trimStart('v').matches(Regex("\\d+\\.\\d+.*")) + val norm = { v: String -> v.trimStart('v') } + val needsUpdate = !isSemver || norm(latestTag) != norm(currentVersion) + + if (!needsUpdate) { showGatewayUpToDate(); return@Thread } + + // Locate the gateway APK among release assets + var apkUrl = GATEWAY_DOWNLOAD_URL + val assets = json.optJSONArray("assets") + if (assets != null) { + for (i in 0 until assets.length()) { + val a = assets.getJSONObject(i) + val name = a.optString("name", "").lowercase() + val url = a.optString("browser_download_url", "") + if ((name.contains("gateway") || name.contains("scale")) && url.isNotEmpty()) { + apkUrl = url; break + } + } + } + val finalUrl = apkUrl + runOnUiThread { + scaleStatusIcon.text = "\uD83D\uDD04" + scaleStatusText.text = getString(R.string.wizard_gateway_update_available) + scaleStatusDetail.text = getString(R.string.wizard_gateway_update_detail) + scaleStatusDetail.setTextColor(0xFFfbbf24.toInt()) + pendingInstallPkg = GATEWAY_PACKAGE + pendingApkDownloadUrl = finalUrl + findViewById(R.id.btnSkipScale).apply { + text = getString(R.string.btn_update_gateway) + setTextColor(0xFFfbbf24.toInt()) + visibility = View.VISIBLE + setOnClickListener { triggerApkDownload(finalUrl) } + } + } + } catch (_: Exception) { + showGatewayUpToDate() + } + }.start() + } + + private fun showGatewayUpToDate() = runOnUiThread { + scaleStatusDetail.text = getString(R.string.wizard_gateway_installed_detail) + scaleStatusDetail.setTextColor(0xFF34d399.toInt()) + } + // ── Connection Test ─────────────────────────────────────────────────── private fun testConnection() { @@ -996,7 +1079,9 @@ class KioskActivity : AppCompatActivity() { showWizard() } if (currentStep == 3 && wizardContainer.visibility == View.VISIBLE) { - checkGatewayStatus() + val statusCard = findViewById(R.id.scaleStatusCard) + // Only re-check if the user has already answered "Yes" (status card visible) + if (statusCard.visibility == View.VISIBLE) checkGatewayStatus() } } diff --git a/evershelf-kiosk/app/src/main/res/layout/activity_kiosk.xml b/evershelf-kiosk/app/src/main/res/layout/activity_kiosk.xml index 0adc4fd..688a4d2 100644 --- a/evershelf-kiosk/app/src/main/res/layout/activity_kiosk.xml +++ b/evershelf-kiosk/app/src/main/res/layout/activity_kiosk.xml @@ -302,7 +302,7 @@ - + + + + + + + + + + + + android:layout_marginBottom="16dp" + android:visibility="gone"> + + android:layout_marginTop="16dp" + android:visibility="gone"> + + style="@style/Widget.MaterialComponents.Button.OutlinedButton" + android:strokeColor="#7c3aed" + android:textColor="#a78bfa" + android:layout_marginTop="12dp" + android:visibility="gone" /> diff --git a/evershelf-kiosk/app/src/main/res/values-de/strings.xml b/evershelf-kiosk/app/src/main/res/values-de/strings.xml new file mode 100644 index 0000000..b0da8cf --- /dev/null +++ b/evershelf-kiosk/app/src/main/res/values-de/strings.xml @@ -0,0 +1,28 @@ + + + EverShelf Kiosk + + + Smart-Waage (Optional) + Um eine Bluetooth-Küchenwaage zu verwenden, musst du die EverShelf Scale Gateway App separat installieren. + Hast du eine Bluetooth-Küchenwaage? + ✅ Ja, ich habe eine Waage + ➡️ Nein, überspringen + + + Scale Gateway installiert ✅ + Wird beim Fortfahren im Hintergrund gestartet. + Scale Gateway nicht installiert + Installiere die Scale Gateway App, um eine Bluetooth-Waage zu nutzen. + Prüfe auf Updates… + Scale Gateway ist aktuell. + Update für Scale Gateway verfügbar + Tippe auf den Button, um jetzt zu aktualisieren. + + + Zurück + 🚀 EverShelf starten + 🚀 Ohne Waage starten + 📥 Scale Gateway installieren + 📥 Scale Gateway aktualisieren + diff --git a/evershelf-kiosk/app/src/main/res/values-it/strings.xml b/evershelf-kiosk/app/src/main/res/values-it/strings.xml new file mode 100644 index 0000000..adcdb45 --- /dev/null +++ b/evershelf-kiosk/app/src/main/res/values-it/strings.xml @@ -0,0 +1,28 @@ + + + EverShelf Kiosk + + + Bilancia Smart (Opzionale) + Per usare una bilancia da cucina Bluetooth, devi installare l\'app EverShelf Scale Gateway separatamente. + Hai una bilancia smart Bluetooth? + ✅ Sì, ho una bilancia + ➡️ No, salta questo passaggio + + + Scale Gateway installato ✅ + Verrà avviato in background quando procedi. + Scale Gateway non installato + Installa l\'app Scale Gateway per usare una bilancia Bluetooth. + Controllo aggiornamenti… + Scale Gateway è aggiornato. + Aggiornamento disponibile per Scale Gateway + Tocca il pulsante qui sotto per aggiornarlo ora. + + + Indietro + 🚀 Avvia EverShelf + 🚀 Avvia senza bilancia + 📥 Installa Scale Gateway + 📥 Aggiorna Scale Gateway + diff --git a/evershelf-kiosk/app/src/main/res/values/strings.xml b/evershelf-kiosk/app/src/main/res/values/strings.xml index 6d0e1be..2133a99 100644 --- a/evershelf-kiosk/app/src/main/res/values/strings.xml +++ b/evershelf-kiosk/app/src/main/res/values/strings.xml @@ -1,3 +1,27 @@ EverShelf Kiosk + + + Smart Scale (Optional) + To use a Bluetooth kitchen scale, you need the EverShelf Scale Gateway app installed separately. + Do you have a Bluetooth smart scale? + ✅ Yes, I have a scale + ➡️ No, skip this step + + + Scale Gateway installed ✅ + Will be launched in the background when you proceed. + Scale Gateway not installed + Install the Scale Gateway app to use a Bluetooth scale. + Checking for updates… + Scale Gateway is up to date. + Update available for Scale Gateway + Tap the button below to update it now. + + + Back + 🚀 Launch EverShelf + 🚀 Launch without scale + 📥 Install Scale Gateway + 📥 Update Scale Gateway