feat(kiosk): language selection as first setup step + screensaver step
- SetupActivity: new Step 0 — language picker (IT/EN/DE) with large buttons, hardcoded trilingual title so it's always readable; saves 'kiosk_language' pref, calls recreate() via onSaveInstanceState to reload the Activity in chosen locale - SetupActivity: new Step 5 — screensaver toggle (before Done), saves 'screensaver_enabled' - All existing steps shifted: Welcome→1, Permissions→2, Server→3, Scale→4, Done→6 - Progress dots updated to 5 dots (steps 1-5) - attachBaseContext override in SetupActivity, KioskActivity, SettingsActivity to apply the saved locale to all Activities via SetupActivity.applyLocale() - buildSummary now shows language, screensaver setting, and scale status - New string resources: setup_screensaver_*, summary_lang, summary_scale_skip, summary_screensaver_on/off in IT, EN, DE
This commit is contained in:
@@ -104,6 +104,12 @@ class KioskActivity : AppCompatActivity() {
|
|||||||
private const val GITHUB_RELEASES_API = "https://api.github.com/repos/dadaloop82/EverShelf/releases/latest"
|
private const val GITHUB_RELEASES_API = "https://api.github.com/repos/dadaloop82/EverShelf/releases/latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) {
|
||||||
|
val lang = newBase.getSharedPreferences("evershelf_kiosk", Context.MODE_PRIVATE)
|
||||||
|
.getString("kiosk_language", null)
|
||||||
|
super.attachBaseContext(if (lang != null) SetupActivity.applyLocale(newBase, lang) else newBase)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_kiosk)
|
setContentView(R.layout.activity_kiosk)
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
private const val GATEWAY_PACKAGE = "it.dadaloop.evershelf.scalegate"
|
private const val GATEWAY_PACKAGE = "it.dadaloop.evershelf.scalegate"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) {
|
||||||
|
val lang = newBase.getSharedPreferences("evershelf_kiosk", Context.MODE_PRIVATE)
|
||||||
|
.getString("kiosk_language", null)
|
||||||
|
super.attachBaseContext(if (lang != null) SetupActivity.applyLocale(newBase, lang) else newBase)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.content.Intent
|
|||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@@ -27,8 +28,10 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.util.Locale
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@@ -42,11 +45,13 @@ import javax.net.ssl.X509TrustManager
|
|||||||
* The user can always exit (finishAffinity) via the ✕ button.
|
* The user can always exit (finishAffinity) via the ✕ button.
|
||||||
*
|
*
|
||||||
* Steps:
|
* Steps:
|
||||||
* 0 — Welcome / intro / privacy
|
* 0 — Language selection (NEW — always first)
|
||||||
* 1 — Permissions rationale + grant
|
* 1 — Welcome / intro / privacy
|
||||||
* 2 — Server URL + auto-discovery + connection test
|
* 2 — Permissions rationale + grant
|
||||||
* 3 — Smart scale question → gateway info + install
|
* 3 — Server URL + auto-discovery + connection test
|
||||||
* 4 — Done
|
* 4 — Smart scale question → gateway info + install
|
||||||
|
* 5 — Screensaver toggle (NEW)
|
||||||
|
* 6 — Done
|
||||||
*/
|
*/
|
||||||
class SetupActivity : AppCompatActivity() {
|
class SetupActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@@ -54,10 +59,12 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
private var currentStep = 0
|
private var currentStep = 0
|
||||||
|
|
||||||
// Step containers
|
// Step containers
|
||||||
|
private lateinit var stepLanguage: LinearLayout
|
||||||
private lateinit var stepWelcome: LinearLayout
|
private lateinit var stepWelcome: LinearLayout
|
||||||
private lateinit var stepPermissions: LinearLayout
|
private lateinit var stepPermissions: LinearLayout
|
||||||
private lateinit var stepServer: LinearLayout
|
private lateinit var stepServer: LinearLayout
|
||||||
private lateinit var stepScale: LinearLayout
|
private lateinit var stepScale: LinearLayout
|
||||||
|
private lateinit var stepScreensaver: LinearLayout
|
||||||
private lateinit var stepDone: LinearLayout
|
private lateinit var stepDone: LinearLayout
|
||||||
|
|
||||||
// Progress dots
|
// Progress dots
|
||||||
@@ -82,6 +89,9 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
private lateinit var gatewayProgressText: TextView
|
private lateinit var gatewayProgressText: TextView
|
||||||
private lateinit var step3NextButtons: LinearLayout
|
private lateinit var step3NextButtons: LinearLayout
|
||||||
|
|
||||||
|
// Screensaver step
|
||||||
|
private lateinit var setupSwitchScreensaver: SwitchMaterial
|
||||||
|
|
||||||
// Done step
|
// Done step
|
||||||
private lateinit var summaryText: TextView
|
private lateinit var summaryText: TextView
|
||||||
|
|
||||||
@@ -99,17 +109,35 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
private val discoverCancelled = AtomicBoolean(false)
|
private val discoverCancelled = AtomicBoolean(false)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val PREFS_NAME = "evershelf_kiosk"
|
private const val PREFS_NAME = "evershelf_kiosk"
|
||||||
private const val KEY_URL = "evershelf_url"
|
private const val KEY_URL = "evershelf_url"
|
||||||
private const val KEY_SETUP_COMPLETE = "setup_complete"
|
private const val KEY_SETUP_COMPLETE = "setup_complete"
|
||||||
private const val KEY_HAS_SCALE = "has_scale"
|
private const val KEY_HAS_SCALE = "has_scale"
|
||||||
private const val GATEWAY_PACKAGE = "it.dadaloop.evershelf.scalegate"
|
private const val KEY_LANGUAGE = "kiosk_language"
|
||||||
|
private const val KEY_SCREENSAVER = "screensaver_enabled"
|
||||||
|
private const val GATEWAY_PACKAGE = "it.dadaloop.evershelf.scalegate"
|
||||||
private const val GATEWAY_DOWNLOAD_URL =
|
private const val GATEWAY_DOWNLOAD_URL =
|
||||||
"https://github.com/dadaloop82/EverShelf/releases/latest/download/evershelf-scale-gateway.apk"
|
"https://github.com/dadaloop82/EverShelf/releases/latest/download/evershelf-scale-gateway.apk"
|
||||||
private const val INSTALL_PERM_REQUEST = 2001
|
private const val INSTALL_PERM_REQUEST = 2001
|
||||||
private const val INSTALL_CONFIRM_REQUEST = 2002
|
private const val INSTALL_CONFIRM_REQUEST = 2002
|
||||||
private const val UNINSTALL_REQUEST = 2003
|
private const val UNINSTALL_REQUEST = 2003
|
||||||
private const val PERMISSION_REQUEST_CODE = 2004
|
private const val PERMISSION_REQUEST_CODE = 2004
|
||||||
|
|
||||||
|
fun applyLocale(base: Context, lang: String): Context {
|
||||||
|
val locale = Locale(lang)
|
||||||
|
Locale.setDefault(locale)
|
||||||
|
val config = Configuration(base.resources.configuration)
|
||||||
|
config.setLocale(locale)
|
||||||
|
return base.createConfigurationContext(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Locale wrapping ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) {
|
||||||
|
val lang = newBase.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
.getString(KEY_LANGUAGE, null)
|
||||||
|
super.attachBaseContext(if (lang != null) applyLocale(newBase, lang) else newBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Lifecycle ─────────────────────────────────────────────────────────
|
// ── Lifecycle ─────────────────────────────────────────────────────────
|
||||||
@@ -119,12 +147,25 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
setContentView(R.layout.activity_setup)
|
setContentView(R.layout.activity_setup)
|
||||||
prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
bindViews()
|
bindViews()
|
||||||
showStep(0)
|
// Restore step from instance state (e.g. after recreate() for locale change)
|
||||||
|
val savedStep = savedInstanceState?.getInt("step", -1) ?: -1
|
||||||
|
val langAlreadySet = prefs.getString(KEY_LANGUAGE, null) != null
|
||||||
|
showStep(when {
|
||||||
|
savedStep >= 0 -> savedStep
|
||||||
|
langAlreadySet -> 1
|
||||||
|
else -> 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putInt("step", currentStep)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
when (currentStep) {
|
when (currentStep) {
|
||||||
0 -> confirmExit()
|
0 -> confirmExit()
|
||||||
|
1 -> showStep(0) // back to language
|
||||||
else -> showStep(currentStep - 1)
|
else -> showStep(currentStep - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,10 +180,12 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun bindViews() {
|
private fun bindViews() {
|
||||||
progressDots = findViewById(R.id.setupProgressDots)
|
progressDots = findViewById(R.id.setupProgressDots)
|
||||||
|
stepLanguage = findViewById(R.id.stepLanguage)
|
||||||
stepWelcome = findViewById(R.id.stepWelcome)
|
stepWelcome = findViewById(R.id.stepWelcome)
|
||||||
stepPermissions = findViewById(R.id.stepPermissions)
|
stepPermissions = findViewById(R.id.stepPermissions)
|
||||||
stepServer = findViewById(R.id.stepServer)
|
stepServer = findViewById(R.id.stepServer)
|
||||||
stepScale = findViewById(R.id.stepScale)
|
stepScale = findViewById(R.id.stepScale)
|
||||||
|
stepScreensaver = findViewById(R.id.stepScreensaver)
|
||||||
stepDone = findViewById(R.id.stepDone)
|
stepDone = findViewById(R.id.stepDone)
|
||||||
|
|
||||||
// Server step
|
// Server step
|
||||||
@@ -164,6 +207,11 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
gatewayProgressText = findViewById(R.id.gatewayProgressText)
|
gatewayProgressText = findViewById(R.id.gatewayProgressText)
|
||||||
step3NextButtons = findViewById(R.id.step3NextButtons)
|
step3NextButtons = findViewById(R.id.step3NextButtons)
|
||||||
|
|
||||||
|
// Screensaver step
|
||||||
|
setupSwitchScreensaver = findViewById(R.id.setupSwitchScreensaver)
|
||||||
|
// Pre-fill saved screensaver pref
|
||||||
|
setupSwitchScreensaver.isChecked = prefs.getBoolean(KEY_SCREENSAVER, false)
|
||||||
|
|
||||||
// Done step
|
// Done step
|
||||||
summaryText = findViewById(R.id.setupSummaryText)
|
summaryText = findViewById(R.id.setupSummaryText)
|
||||||
|
|
||||||
@@ -174,19 +222,26 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
val savedUrl = prefs.getString(KEY_URL, "") ?: ""
|
val savedUrl = prefs.getString(KEY_URL, "") ?: ""
|
||||||
if (savedUrl.isNotEmpty()) urlEdit.setText(savedUrl)
|
if (savedUrl.isNotEmpty()) urlEdit.setText(savedUrl)
|
||||||
|
|
||||||
|
// ── Language ─────────────────────────────────────────────────────
|
||||||
|
// Highlight already-selected language button
|
||||||
|
highlightSelectedLang()
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangIt).setOnClickListener { selectLanguage("it") }
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangEn).setOnClickListener { selectLanguage("en") }
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangDe).setOnClickListener { selectLanguage("de") }
|
||||||
|
|
||||||
// ── Welcome ──────────────────────────────────────────────────────
|
// ── Welcome ──────────────────────────────────────────────────────
|
||||||
findViewById<MaterialButton>(R.id.btnSetupExit).setOnClickListener { confirmExit() }
|
findViewById<MaterialButton>(R.id.btnSetupExit).setOnClickListener { confirmExit() }
|
||||||
findViewById<MaterialButton>(R.id.btnWelcomeStart).setOnClickListener { showStep(1) }
|
findViewById<MaterialButton>(R.id.btnWelcomeStart).setOnClickListener { showStep(2) }
|
||||||
|
|
||||||
// ── Permissions ──────────────────────────────────────────────────
|
// ── Permissions ──────────────────────────────────────────────────
|
||||||
findViewById<MaterialButton>(R.id.btnGrantPerms).setOnClickListener { requestPermissions() }
|
findViewById<MaterialButton>(R.id.btnGrantPerms).setOnClickListener { requestPermissions() }
|
||||||
findViewById<MaterialButton>(R.id.btnPermsBack).setOnClickListener { showStep(0) }
|
findViewById<MaterialButton>(R.id.btnPermsBack).setOnClickListener { showStep(1) }
|
||||||
findViewById<MaterialButton>(R.id.btnPermsNext).setOnClickListener { showStep(2) }
|
findViewById<MaterialButton>(R.id.btnPermsNext).setOnClickListener { showStep(3) }
|
||||||
|
|
||||||
// ── Server ───────────────────────────────────────────────────────
|
// ── Server ───────────────────────────────────────────────────────
|
||||||
btnDiscover.setOnClickListener { autoDiscover() }
|
btnDiscover.setOnClickListener { autoDiscover() }
|
||||||
btnTestUrl.setOnClickListener { testConnection() }
|
btnTestUrl.setOnClickListener { testConnection() }
|
||||||
findViewById<MaterialButton>(R.id.btnServerBack).setOnClickListener { showStep(1) }
|
findViewById<MaterialButton>(R.id.btnServerBack).setOnClickListener { showStep(2) }
|
||||||
findViewById<MaterialButton>(R.id.btnServerNext).setOnClickListener {
|
findViewById<MaterialButton>(R.id.btnServerNext).setOnClickListener {
|
||||||
val url = urlEdit.text.toString().trim()
|
val url = urlEdit.text.toString().trim()
|
||||||
if (url.isEmpty()) {
|
if (url.isEmpty()) {
|
||||||
@@ -195,7 +250,7 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
prefs.edit().putString(KEY_URL, url).apply()
|
prefs.edit().putString(KEY_URL, url).apply()
|
||||||
ErrorReporter.init(this, url)
|
ErrorReporter.init(this, url)
|
||||||
showStep(3)
|
showStep(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Scale ─────────────────────────────────────────────────────────
|
// ── Scale ─────────────────────────────────────────────────────────
|
||||||
@@ -208,36 +263,67 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
findViewById<MaterialButton>(R.id.btnScaleNo).setOnClickListener {
|
findViewById<MaterialButton>(R.id.btnScaleNo).setOnClickListener {
|
||||||
prefs.edit().putBoolean(KEY_HAS_SCALE, false).apply()
|
prefs.edit().putBoolean(KEY_HAS_SCALE, false).apply()
|
||||||
showStep(4)
|
showStep(5)
|
||||||
}
|
}
|
||||||
btnInstallGateway.setOnClickListener {
|
btnInstallGateway.setOnClickListener {
|
||||||
pendingApkDownloadUrl = GATEWAY_DOWNLOAD_URL
|
pendingApkDownloadUrl = GATEWAY_DOWNLOAD_URL
|
||||||
triggerApkDownload(GATEWAY_DOWNLOAD_URL)
|
triggerApkDownload(GATEWAY_DOWNLOAD_URL)
|
||||||
}
|
}
|
||||||
findViewById<MaterialButton>(R.id.btnScaleBack).setOnClickListener { showStep(2) }
|
findViewById<MaterialButton>(R.id.btnScaleBack).setOnClickListener { showStep(3) }
|
||||||
findViewById<MaterialButton>(R.id.btnScaleNext).setOnClickListener {
|
findViewById<MaterialButton>(R.id.btnScaleNext).setOnClickListener {
|
||||||
prefs.edit().putBoolean(KEY_HAS_SCALE, true).apply()
|
prefs.edit().putBoolean(KEY_HAS_SCALE, true).apply()
|
||||||
showStep(4)
|
showStep(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Screensaver ───────────────────────────────────────────────────
|
||||||
|
findViewById<MaterialButton>(R.id.btnScreensaverBack).setOnClickListener { showStep(4) }
|
||||||
|
findViewById<MaterialButton>(R.id.btnScreensaverNext).setOnClickListener {
|
||||||
|
prefs.edit().putBoolean(KEY_SCREENSAVER, setupSwitchScreensaver.isChecked).apply()
|
||||||
|
showStep(6)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Done ──────────────────────────────────────────────────────────
|
// ── Done ──────────────────────────────────────────────────────────
|
||||||
findViewById<MaterialButton>(R.id.btnLaunch).setOnClickListener { finishSetup() }
|
findViewById<MaterialButton>(R.id.btnLaunch).setOnClickListener { finishSetup() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Language selection ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private fun selectLanguage(lang: String) {
|
||||||
|
prefs.edit().putString(KEY_LANGUAGE, lang).apply()
|
||||||
|
// Save step=1 so after recreate we land on Welcome
|
||||||
|
currentStep = 1
|
||||||
|
recreate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun highlightSelectedLang() {
|
||||||
|
val saved = prefs.getString(KEY_LANGUAGE, null) ?: return
|
||||||
|
val (btnIt, btnEn, btnDe) = Triple(
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangIt),
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangEn),
|
||||||
|
findViewById<MaterialButton>(R.id.btnLangDe)
|
||||||
|
)
|
||||||
|
// Add checkmark to selected
|
||||||
|
btnIt.text = if (saved == "it") "✅ 🇮🇹 Italiano" else "🇮🇹 Italiano"
|
||||||
|
btnEn.text = if (saved == "en") "✅ 🇬🇧 English" else "🇬🇧 English"
|
||||||
|
btnDe.text = if (saved == "de") "✅ 🇩🇪 Deutsch" else "🇩🇪 Deutsch"
|
||||||
|
}
|
||||||
|
|
||||||
// ── Step navigation ───────────────────────────────────────────────────
|
// ── Step navigation ───────────────────────────────────────────────────
|
||||||
|
|
||||||
private fun showStep(step: Int) {
|
private fun showStep(step: Int) {
|
||||||
currentStep = step
|
currentStep = step
|
||||||
stepWelcome.visibility = if (step == 0) View.VISIBLE else View.GONE
|
stepLanguage.visibility = if (step == 0) View.VISIBLE else View.GONE
|
||||||
stepPermissions.visibility = if (step == 1) View.VISIBLE else View.GONE
|
stepWelcome.visibility = if (step == 1) View.VISIBLE else View.GONE
|
||||||
stepServer.visibility = if (step == 2) View.VISIBLE else View.GONE
|
stepPermissions.visibility = if (step == 2) View.VISIBLE else View.GONE
|
||||||
stepScale.visibility = if (step == 3) View.VISIBLE else View.GONE
|
stepServer.visibility = if (step == 3) View.VISIBLE else View.GONE
|
||||||
stepDone.visibility = if (step == 4) View.VISIBLE else View.GONE
|
stepScale.visibility = if (step == 4) View.VISIBLE else View.GONE
|
||||||
|
stepScreensaver.visibility = if (step == 5) View.VISIBLE else View.GONE
|
||||||
|
stepDone.visibility = if (step == 6) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
updateProgressDots()
|
updateProgressDots()
|
||||||
|
|
||||||
// Reset scale step when entering it
|
// Reset scale step when entering it
|
||||||
if (step == 3) {
|
if (step == 4) {
|
||||||
scaleQuestionCard.visibility = View.VISIBLE
|
scaleQuestionCard.visibility = View.VISIBLE
|
||||||
gatewayInfoCard.visibility = View.GONE
|
gatewayInfoCard.visibility = View.GONE
|
||||||
gatewayInstallCard.visibility = View.GONE
|
gatewayInstallCard.visibility = View.GONE
|
||||||
@@ -245,10 +331,10 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build summary when entering done step
|
// Build summary when entering done step
|
||||||
if (step == 4) buildSummary()
|
if (step == 6) buildSummary()
|
||||||
|
|
||||||
// Cancel auto-discover when leaving server step
|
// Cancel auto-discover when leaving server step
|
||||||
if (step != 2) discoverCancelled.set(true)
|
if (step != 3) discoverCancelled.set(true)
|
||||||
|
|
||||||
// Scroll to top
|
// Scroll to top
|
||||||
try { findViewById<ScrollView>(R.id.setupScrollView).scrollTo(0, 0) } catch (_: Exception) {}
|
try { findViewById<ScrollView>(R.id.setupScrollView).scrollTo(0, 0) } catch (_: Exception) {}
|
||||||
@@ -256,10 +342,11 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun updateProgressDots() {
|
private fun updateProgressDots() {
|
||||||
progressDots.removeAllViews()
|
progressDots.removeAllViews()
|
||||||
// 4 dots (steps 1–4); step 0 welcome uses no dots
|
// Show 5 dots for steps 1-5; step 0 (language) and step 6 (done) have no dots
|
||||||
val active = maxOf(currentStep, 1)
|
if (currentStep == 0 || currentStep == 6) return
|
||||||
|
val active = currentStep // 1..5
|
||||||
val density = resources.displayMetrics.density
|
val density = resources.displayMetrics.density
|
||||||
for (i in 1..4) {
|
for (i in 1..5) {
|
||||||
val dot = View(this)
|
val dot = View(this)
|
||||||
val sizeDp = if (i == active) 10 else 7
|
val sizeDp = if (i == active) 10 else 7
|
||||||
val px = (sizeDp * density).toInt()
|
val px = (sizeDp * density).toInt()
|
||||||
@@ -753,16 +840,21 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
// ── Summary / Finish ─────────────────────────────────────────────────
|
// ── Summary / Finish ─────────────────────────────────────────────────
|
||||||
|
|
||||||
private fun buildSummary() {
|
private fun buildSummary() {
|
||||||
val url = prefs.getString(KEY_URL, "") ?: ""
|
val url = prefs.getString(KEY_URL, "") ?: ""
|
||||||
val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false)
|
val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false)
|
||||||
val gwOk = hasScale && isGatewayInstalled()
|
val screensOn = setupSwitchScreensaver.isChecked
|
||||||
|
val gwOk = hasScale && isGatewayInstalled()
|
||||||
|
val lang = prefs.getString(KEY_LANGUAGE, "it") ?: "it"
|
||||||
|
val langLabel = when (lang) { "en" -> "English 🇬🇧"; "de" -> "Deutsch 🇩🇪"; else -> "Italiano 🇮🇹" }
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
if (url.isNotEmpty()) sb.appendLine("🌐 Server: $url")
|
sb.appendLine("🌐 ${getString(R.string.summary_lang)}: $langLabel")
|
||||||
|
if (url.isNotEmpty()) sb.appendLine("🖥️ Server: $url")
|
||||||
sb.appendLine(when {
|
sb.appendLine(when {
|
||||||
gwOk -> "✅ Scale Gateway: installato"
|
gwOk -> "✅ Scale Gateway: ${getString(R.string.wizard_gateway_installed)}"
|
||||||
hasScale -> "⚠️ Scale Gateway: non ancora installato"
|
hasScale -> "⚠️ Scale Gateway: ${getString(R.string.wizard_gateway_not_installed)}"
|
||||||
else -> "⏭ Bilancia: non configurata"
|
else -> "⏭ ${getString(R.string.summary_scale_skip)}"
|
||||||
})
|
})
|
||||||
|
sb.appendLine(if (screensOn) "🌙 ${getString(R.string.summary_screensaver_on)}" else "💡 ${getString(R.string.summary_screensaver_off)}")
|
||||||
summaryText.text = sb.toString().trimEnd()
|
summaryText.text = sb.toString().trimEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,68 @@
|
|||||||
android:paddingBottom="40dp">
|
android:paddingBottom="40dp">
|
||||||
|
|
||||||
<!-- ════════════════════════════════════════════
|
<!-- ════════════════════════════════════════════
|
||||||
STEP 0 — Welcome / Intro / Privacy
|
STEP 0 — Language selection
|
||||||
|
════════════════════════════════════════════ -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/stepLanguage"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="🌐"
|
||||||
|
android:textSize="64sp"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<!-- Title shown in all 3 languages so it's always readable -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Scegli la lingua\nChoose your language\nSprache wählen"
|
||||||
|
android:textColor="#f1f5f9"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:lineSpacingExtra="4dp"
|
||||||
|
android:layout_marginBottom="40dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnLangIt"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:text="🇮🇹 Italiano"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#7c3aed"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnLangEn"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:text="🇬🇧 English"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#1e40af"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnLangDe"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:text="🇩🇪 Deutsch"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#b91c1c" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- ════════════════════════════════════════════
|
||||||
|
STEP 1 — Welcome / Intro / Privacy
|
||||||
════════════════════════════════════════════ -->
|
════════════════════════════════════════════ -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/stepWelcome"
|
android:id="@+id/stepWelcome"
|
||||||
@@ -880,7 +941,119 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- ════════════════════════════════════════════
|
<!-- ════════════════════════════════════════════
|
||||||
STEP 4 — Done
|
STEP 5 — Screensaver
|
||||||
|
════════════════════════════════════════════ -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/stepScreensaver"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="🌙"
|
||||||
|
android:textSize="52sp"
|
||||||
|
android:layout_marginBottom="12dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/tvScreensaverTitle"
|
||||||
|
android:text="@string/setup_screensaver_title"
|
||||||
|
android:textColor="#f1f5f9"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvScreensaverDesc"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Mostra un orologio con fatti utili dopo 5 minuti di inattività. Di default è disattivato (lo schermo resta sempre acceso)."
|
||||||
|
android:textColor="#94a3b8"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:lineSpacingExtra="4dp"
|
||||||
|
android:layout_marginBottom="28dp" />
|
||||||
|
|
||||||
|
<!-- Toggle card -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="@drawable/card_background"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginBottom="32dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvScreensaverToggleLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/setup_screensaver_toggle_label"
|
||||||
|
android:textColor="#f1f5f9"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="4dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvScreensaverToggleHint"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/setup_screensaver_toggle_hint"
|
||||||
|
android:textColor="#64748b"
|
||||||
|
android:textSize="13sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/setupSwitchScreensaver"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Navigation -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnScreensaverBack"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="← Indietro"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:strokeColor="#334155"
|
||||||
|
android:textColor="#64748b"
|
||||||
|
android:layout_marginEnd="10dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnScreensaverNext"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:text="Avanti →"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#7c3aed" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- ════════════════════════════════════════════
|
||||||
|
STEP 6 — Done
|
||||||
════════════════════════════════════════════ -->
|
════════════════════════════════════════════ -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/stepDone"
|
android:id="@+id/stepDone"
|
||||||
|
|||||||
@@ -60,4 +60,15 @@
|
|||||||
<string name="wizard_server_ok_detail">Fehlerberichterstattung aktiv — Installationsfehler werden automatisch an GitHub Issues gesendet.</string>
|
<string name="wizard_server_ok_detail">Fehlerberichterstattung aktiv — Installationsfehler werden automatisch an GitHub Issues gesendet.</string>
|
||||||
<string name="wizard_server_error">Server nicht erreichbar ⚠️</string>
|
<string name="wizard_server_error">Server nicht erreichbar ⚠️</string>
|
||||||
<string name="wizard_server_error_detail">Fehler werden GitHub Issues nicht erreichen. URL in Schritt 2 prüfen.</string>
|
<string name="wizard_server_error_detail">Fehler werden GitHub Issues nicht erreichen. URL in Schritt 2 prüfen.</string>
|
||||||
|
<!-- Bildschirmschoner-Schritt -->
|
||||||
|
<string name="setup_screensaver_title">Bildschirmschoner</string>
|
||||||
|
<string name="setup_screensaver_desc">Zeigt nach 5 Minuten Inaktivität eine Uhr mit nützlichen Fakten. Standardmäßig deaktiviert (Bildschirm bleibt immer an).</string>
|
||||||
|
<string name="setup_screensaver_toggle_label">Bildschirmschoner aktivieren</string>
|
||||||
|
<string name="setup_screensaver_toggle_hint">Wenn deaktiviert, bleibt der Bildschirm immer an.</string>
|
||||||
|
|
||||||
|
<!-- Zusammenfassung -->
|
||||||
|
<string name="summary_lang">Sprache</string>
|
||||||
|
<string name="summary_scale_skip">Waage: nicht konfiguriert</string>
|
||||||
|
<string name="summary_screensaver_on">Bildschirmschoner: aktiv</string>
|
||||||
|
<string name="summary_screensaver_off">Bildschirm immer an (Bildschirmschoner deaktiviert)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -60,4 +60,15 @@
|
|||||||
<string name="wizard_server_ok_detail">Segnalazione errori attiva — i problemi di installazione vengono inviati automaticamente alle GitHub Issues.</string>
|
<string name="wizard_server_ok_detail">Segnalazione errori attiva — i problemi di installazione vengono inviati automaticamente alle GitHub Issues.</string>
|
||||||
<string name="wizard_server_error">Server non raggiungibile ⚠️</string>
|
<string name="wizard_server_error">Server non raggiungibile ⚠️</string>
|
||||||
<string name="wizard_server_error_detail">Gli errori non raggiungeranno GitHub Issues. Verifica l\'URL inserito al passaggio 2.</string>
|
<string name="wizard_server_error_detail">Gli errori non raggiungeranno GitHub Issues. Verifica l\'URL inserito al passaggio 2.</string>
|
||||||
|
<!-- Passo salvaschermo -->
|
||||||
|
<string name="setup_screensaver_title">Salvaschermo</string>
|
||||||
|
<string name="setup_screensaver_desc">Mostra un orologio con fatti utili dopo 5 minuti di inattività. Di default è disattivato (lo schermo resta sempre acceso).</string>
|
||||||
|
<string name="setup_screensaver_toggle_label">Attiva salvaschermo</string>
|
||||||
|
<string name="setup_screensaver_toggle_hint">Se disattivo, lo schermo resta sempre acceso.</string>
|
||||||
|
|
||||||
|
<!-- Riepilogo -->
|
||||||
|
<string name="summary_lang">Lingua</string>
|
||||||
|
<string name="summary_scale_skip">Bilancia: non configurata</string>
|
||||||
|
<string name="summary_screensaver_on">Salvaschermo: attivo</string>
|
||||||
|
<string name="summary_screensaver_off">Schermo sempre acceso (salvaschermo disattivato)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -59,4 +59,15 @@
|
|||||||
<string name="wizard_server_ok_detail">Error reporting is active — install failures will be sent to GitHub Issues automatically.</string>
|
<string name="wizard_server_ok_detail">Error reporting is active — install failures will be sent to GitHub Issues automatically.</string>
|
||||||
<string name="wizard_server_error">Server not reachable ⚠️</string>
|
<string name="wizard_server_error">Server not reachable ⚠️</string>
|
||||||
<string name="wizard_server_error_detail">Install errors won\'t reach GitHub Issues. Check the URL entered in step 2.</string>
|
<string name="wizard_server_error_detail">Install errors won\'t reach GitHub Issues. Check the URL entered in step 2.</string>
|
||||||
|
<!-- Screensaver step -->
|
||||||
|
<string name="setup_screensaver_title">Screensaver</string>
|
||||||
|
<string name="setup_screensaver_desc">Shows a clock with useful facts after 5 minutes of inactivity. Off by default (screen stays always on).</string>
|
||||||
|
<string name="setup_screensaver_toggle_label">Enable screensaver</string>
|
||||||
|
<string name="setup_screensaver_toggle_hint">If disabled, the screen stays always on.</string>
|
||||||
|
|
||||||
|
<!-- Summary -->
|
||||||
|
<string name="summary_lang">Language</string>
|
||||||
|
<string name="summary_scale_skip">Scale: not configured</string>
|
||||||
|
<string name="summary_screensaver_on">Screensaver: enabled</string>
|
||||||
|
<string name="summary_screensaver_off">Screen always on (screensaver disabled)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user