feat: MVP implementation - Kiosk Browser
- Fullscreen WebView with immersive mode - URL whitelist system - Admin PIN-protected settings - Boot receiver for auto-launch - Idle timeout with homepage reset - Lock Task Mode support - Material Design 3 UI Team: Pluto (coordinator), Margaret, Spirit
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
package farm.hobbs.kioskbrowser
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import farm.hobbs.kioskbrowser.databinding.ActivityAdminBinding
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import android.text.InputType
|
||||
import android.widget.EditText
|
||||
|
||||
class AdminActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityAdminBinding
|
||||
private val adminPin = "1234" // Default PIN - should be configurable
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Require PIN before showing settings
|
||||
showPinDialog()
|
||||
}
|
||||
|
||||
private fun showPinDialog() {
|
||||
val input = EditText(this).apply {
|
||||
inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
|
||||
hint = "Enter Admin PIN"
|
||||
}
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle("Admin Access")
|
||||
.setMessage("Enter PIN to access settings")
|
||||
.setView(input)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
if (input.text.toString() == getStoredPin()) {
|
||||
setupUI()
|
||||
} else {
|
||||
Toast.makeText(this, "Invalid PIN", Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
.setNegativeButton("Cancel") { _, _ -> finish() }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun getStoredPin(): String {
|
||||
return runBlocking {
|
||||
dataStore.data.first()[stringPreferencesKey("admin_pin")] ?: adminPin
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUI() {
|
||||
binding = ActivityAdminBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
loadCurrentSettings()
|
||||
|
||||
binding.btnSave.setOnClickListener {
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
binding.btnExit.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.btnExitKiosk.setOnClickListener {
|
||||
// Exit kiosk mode completely
|
||||
finishAffinity()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCurrentSettings() {
|
||||
runBlocking {
|
||||
dataStore.data.first().let { prefs ->
|
||||
binding.etHomepage.setText(
|
||||
prefs[stringPreferencesKey("homepage")] ?: "https://hobbs.farm"
|
||||
)
|
||||
binding.etWhitelist.setText(
|
||||
prefs[stringPreferencesKey("whitelist")] ?: "hobbs.farm"
|
||||
)
|
||||
binding.etIdleTimeout.setText(
|
||||
prefs[stringPreferencesKey("idle_timeout")] ?: "300"
|
||||
)
|
||||
binding.etAdminPin.setText(
|
||||
prefs[stringPreferencesKey("admin_pin")] ?: "1234"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSettings() {
|
||||
runBlocking {
|
||||
dataStore.edit { prefs ->
|
||||
prefs[stringPreferencesKey("homepage")] = binding.etHomepage.text.toString()
|
||||
prefs[stringPreferencesKey("whitelist")] = binding.etWhitelist.text.toString()
|
||||
prefs[stringPreferencesKey("idle_timeout")] = binding.etIdleTimeout.text.toString()
|
||||
prefs[stringPreferencesKey("admin_pin")] = binding.etAdminPin.text.toString()
|
||||
}
|
||||
}
|
||||
Toast.makeText(this, "Settings saved", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user