From cfcba32c4521c4bcd4d9b9cd55ed099a962f8feb Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Mon, 4 May 2026 17:11:17 +0000 Subject: [PATCH] fix(kiosk): permissions button transforms to 'Continue' after grant + fix subnet detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../dadaloop/evershelf/kiosk/SetupActivity.kt | 51 ++++++++++++++----- .../app/src/main/res/values-de/strings.xml | 3 +- .../app/src/main/res/values-it/strings.xml | 3 +- .../app/src/main/res/values/strings.xml | 3 +- 4 files changed, 42 insertions(+), 18 deletions(-) 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 21e0e8a..25d0997 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 @@ -102,6 +102,7 @@ class SetupActivity : AppCompatActivity() { // Permissions step private lateinit var permsGrantedCard: LinearLayout + private lateinit var btnGrantPerms: MaterialButton // APK install state (for gateway) private var pendingApkDownloadUrl = "" @@ -221,7 +222,8 @@ class SetupActivity : AppCompatActivity() { summaryText = findViewById(R.id.setupSummaryText) // Permissions step - permsGrantedCard = findViewById(R.id.permsGrantedCard) + permsGrantedCard = findViewById(R.id.permsGrantedCard) + btnGrantPerms = findViewById(R.id.btnGrantPerms) // Pre-fill saved URL val savedUrl = prefs.getString(KEY_URL, "") ?: "" @@ -239,7 +241,7 @@ class SetupActivity : AppCompatActivity() { findViewById(R.id.btnWelcomeStart).setOnClickListener { showStep(2) } // ── Permissions ────────────────────────────────────────────────── - findViewById(R.id.btnGrantPerms).setOnClickListener { requestPermissions() } + btnGrantPerms.setOnClickListener { requestPermissions() } findViewById(R.id.btnPermsBack).setOnClickListener { showStep(1) } findViewById(R.id.btnPermsNext).setOnClickListener { showStep(3) } @@ -408,8 +410,7 @@ class SetupActivity : AppCompatActivity() { needed.add(Manifest.permission.READ_EXTERNAL_STORAGE) } if (needed.isEmpty()) { - // Already granted — show confirmation and allow next - permsGrantedCard.visibility = View.VISIBLE + onPermissionsGranted() } else { ActivityCompat.requestPermissions(this, needed.toTypedArray(), PERMISSION_REQUEST_CODE) } @@ -418,12 +419,18 @@ class SetupActivity : AppCompatActivity() { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSION_REQUEST_CODE) { - permsGrantedCard.visibility = View.VISIBLE - // Proceed to next step regardless — user can always grant later - Handler(Looper.getMainLooper()).postDelayed({ showStep(2) }, 600) + onPermissionsGranted() } } + private fun onPermissionsGranted() { + permsGrantedCard.visibility = View.GONE + btnGrantPerms.text = getString(R.string.setup_perms_granted_next) + btnGrantPerms.backgroundTintList = android.content.res.ColorStateList.valueOf(0xFF34d399.toInt()) + btnGrantPerms.setTextColor(0xFF0f172a.toInt()) + btnGrantPerms.setOnClickListener { showStep(3) } + } + // ── Connection Test ─────────────────────────────────────────────────── private fun testConnection() { @@ -516,27 +523,47 @@ class SetupActivity : AppCompatActivity() { discoverStatus.setTextColor(0xFF94a3b8.toInt()) Thread { - // ── 1. Detect subnets via NetworkInterface (not deprecated WifiManager) ── - val subnets = mutableListOf() + // ── 1. Detect subnets — prefer Wi-Fi/Ethernet, skip VPN/cellular ────── + // Prefixes to skip: VPN tunnels, cellular data, hotspot virtuals, etc. + val skipPrefixes = listOf("tun", "ppp", "rmnet", "pdp", "ccmni", + "dummy", "sit", "gre", "v4-", "v6-", "p2p", "ham", "nordlynx") + val wifiSubnets = mutableListOf() // wlan/eth — highest priority + val otherSubnets = mutableListOf() // everything else that is real try { val interfaces = NetworkInterface.getNetworkInterfaces() while (interfaces != null && interfaces.hasMoreElements()) { val intf = interfaces.nextElement() - if (!intf.isUp || intf.isLoopback) continue + if (!intf.isUp || intf.isLoopback || intf.isVirtual) continue + val name = intf.name.lowercase() + if (skipPrefixes.any { name.startsWith(it) }) continue for (addr in intf.interfaceAddresses) { val ip = addr.address if (ip is java.net.Inet4Address && !ip.isLoopbackAddress) { val parts = ip.hostAddress?.split(".") ?: continue - if (parts.size == 4) subnets += "${parts[0]}.${parts[1]}.${parts[2]}" + if (parts.size == 4) { + val subnet = "${parts[0]}.${parts[1]}.${parts[2]}" + if (name.startsWith("wlan") || name.startsWith("eth")) { + if (!wifiSubnets.contains(subnet)) wifiSubnets += subnet + } else { + if (!otherSubnets.contains(subnet)) otherSubnets += subnet + } + } } } } } catch (_: Exception) {} - // Append common fallback subnets (deduped) + // WiFi first, then others, then hardcoded fallbacks (deduped) + val subnets = (wifiSubnets + otherSubnets).toMutableList() for (s in listOf("192.168.1", "192.168.0", "192.168.2", "10.0.0", "10.0.1")) { if (!subnets.contains(s)) subnets += s } + // Show detected subnets in status + val detectedLabel = if (wifiSubnets.isNotEmpty()) + wifiSubnets.joinToString(", ") { "$it.x" } + else getString(R.string.setup_discovering_detail) + runOnUiThread { discoverStatus.text = "📡 $detectedLabel" } + val ports = listOf(80, 8080) val paths = listOf( "/api/index.php?action=get_settings", diff --git a/evershelf-kiosk/app/src/main/res/values-de/strings.xml b/evershelf-kiosk/app/src/main/res/values-de/strings.xml index 16783fa..17da8ef 100644 --- a/evershelf-kiosk/app/src/main/res/values-de/strings.xml +++ b/evershelf-kiosk/app/src/main/res/values-de/strings.xml @@ -8,8 +8,7 @@ EverShelf-Server gefunden und API aktiv! Server erreichbar, aber EverShelf-API nicht gefunden. Pfad prüfen. Server nicht erreichbar - 🔍 Lokales Netzwerk durchsuchen - Suche läuft… + 🔍 Lokales Netzwerk durchsuchen ✅ Berechtigungen erteilt — Weiter → Suche läuft… Suche nach EverShelf-Servern im lokalen Netzwerk… Kein EverShelf-Server automatisch gefunden. URL manuell eingeben. Setup beenden? diff --git a/evershelf-kiosk/app/src/main/res/values-it/strings.xml b/evershelf-kiosk/app/src/main/res/values-it/strings.xml index 05222bd..d6095e3 100644 --- a/evershelf-kiosk/app/src/main/res/values-it/strings.xml +++ b/evershelf-kiosk/app/src/main/res/values-it/strings.xml @@ -8,8 +8,7 @@ Server EverShelf trovato e API attiva! Server raggiungibile ma API EverShelf non trovata. Verifica il percorso. Impossibile raggiungere il server - 🔍 Cerca nella rete locale - Scansione in corso… + 🔍 Cerca nella rete locale ✅ Permessi concessi — Continua → Scansione in corso… Ricerca server EverShelf nella rete locale… Nessun server EverShelf trovato automaticamente. Inserisci l\'URL manualmente. Uscire dalla configurazione? diff --git a/evershelf-kiosk/app/src/main/res/values/strings.xml b/evershelf-kiosk/app/src/main/res/values/strings.xml index 205161f..f51f91c 100644 --- a/evershelf-kiosk/app/src/main/res/values/strings.xml +++ b/evershelf-kiosk/app/src/main/res/values/strings.xml @@ -7,8 +7,7 @@ EverShelf server found and API active! Server reachable but EverShelf API not found. Check the path. Cannot reach server - 🔍 Search local network - Scanning… + 🔍 Search local network ✅ Permissions granted — Continue → Scanning… Searching for EverShelf servers on the local network… No EverShelf server found automatically. Enter the URL manually. Exit setup?