224 lines
8.3 KiB
Kotlin
224 lines
8.3 KiB
Kotlin
package com.dano.test1
|
||
|
||
import android.content.res.Configuration
|
||
import android.net.ConnectivityManager
|
||
import android.net.Network
|
||
import android.net.NetworkCapabilities
|
||
import android.net.NetworkRequest
|
||
import android.os.Bundle
|
||
import android.view.View
|
||
import android.widget.EditText
|
||
import android.widget.LinearLayout
|
||
import android.widget.ProgressBar
|
||
import android.widget.Toast
|
||
import androidx.appcompat.app.AlertDialog
|
||
import androidx.appcompat.app.AppCompatActivity
|
||
import java.io.File
|
||
|
||
class MainActivity : AppCompatActivity() {
|
||
|
||
private lateinit var openingScreenHandler: HandlerOpeningScreen
|
||
|
||
var isInQuestionnaire: Boolean = false
|
||
var isFirstQuestionnairePage: Boolean = false
|
||
|
||
private var progress: ProgressBar? = null
|
||
|
||
// LIVE: Network-Callback (optional für Statusleiste)
|
||
private var netCb: ConnectivityManager.NetworkCallback? = null
|
||
|
||
override fun onCreate(savedInstanceState: Bundle?) {
|
||
super.onCreate(savedInstanceState)
|
||
|
||
// === Offline-Start ermöglichen ===
|
||
// Bedingung: gespeicherter User/Token UND lokale DB vorhanden -> direkt OpeningScreen
|
||
val hasCreds = !TokenStore.getUsername(this).isNullOrBlank() && !TokenStore.getToken(this).isNullOrBlank()
|
||
val hasDb = hasLocalDb()
|
||
if (hasCreds && hasDb) {
|
||
openingScreenHandler = HandlerOpeningScreen(this)
|
||
openingScreenHandler.init()
|
||
return
|
||
}
|
||
|
||
// Sonst: Login-Dialog -> Login -> DB (einmalig) laden -> OpeningScreen
|
||
showLoginThenDownload()
|
||
}
|
||
|
||
/** Prüft, ob die lokale DB-Datei vorhanden ist. */
|
||
private fun hasLocalDb(): Boolean {
|
||
val dbFile = getDatabasePath("questionnaire_database")
|
||
return dbFile != null && dbFile.exists() && dbFile.length() > 0
|
||
}
|
||
|
||
/** Zeigt den Login-Dialog an, führt Login aus und lädt danach einmalig die DB. */
|
||
private fun showLoginThenDownload() {
|
||
val container = LinearLayout(this).apply {
|
||
orientation = LinearLayout.VERTICAL
|
||
setPadding(dp(20), dp(8), dp(20), 0)
|
||
}
|
||
val etUser = EditText(this).apply {
|
||
hint = "Username"
|
||
setSingleLine()
|
||
}
|
||
val etPass = EditText(this).apply {
|
||
hint = "Passwort"
|
||
setSingleLine()
|
||
inputType = android.text.InputType.TYPE_CLASS_TEXT or
|
||
android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||
}
|
||
container.addView(etUser)
|
||
container.addView(etPass)
|
||
|
||
val dialog = AlertDialog.Builder(this)
|
||
.setTitle("Login erforderlich")
|
||
.setView(container)
|
||
.setCancelable(false)
|
||
.setPositiveButton("Login") { _, _ ->
|
||
val user = etUser.text.toString().trim()
|
||
val pass = etPass.text.toString()
|
||
if (user.isEmpty() || pass.isEmpty()) {
|
||
Toast.makeText(this, "Bitte Username & Passwort eingeben", Toast.LENGTH_SHORT).show()
|
||
showLoginThenDownload()
|
||
return@setPositiveButton
|
||
}
|
||
showBusy(true)
|
||
LoginManager.loginUserWithCredentials(
|
||
context = this,
|
||
username = user,
|
||
password = pass,
|
||
onSuccess = { token ->
|
||
// Nach erfolgreichem Login: einmalig komplette DB ziehen
|
||
DatabaseDownloader.downloadAndReplaceDatabase(
|
||
context = this,
|
||
token = token
|
||
) { ok ->
|
||
showBusy(false)
|
||
|
||
// Wenn Download fehlgeschlagen ist, aber evtl. schon eine DB lokal liegt,
|
||
// lassen wir den Nutzer trotzdem weiterarbeiten (Offline).
|
||
if (!ok && !hasLocalDb()) {
|
||
Toast.makeText(this, "Download fehlgeschlagen – keine lokale Datenbank vorhanden", Toast.LENGTH_LONG).show()
|
||
// Zurück zum Login, damit man es erneut probieren kann
|
||
showLoginThenDownload()
|
||
return@downloadAndReplaceDatabase
|
||
}
|
||
|
||
if (!ok) {
|
||
Toast.makeText(this, "Download fehlgeschlagen – arbeite offline mit vorhandener DB", Toast.LENGTH_LONG).show()
|
||
}
|
||
|
||
// Opening-Screen starten
|
||
openingScreenHandler = HandlerOpeningScreen(this)
|
||
openingScreenHandler.init()
|
||
openingScreenHandler.refreshHeaderStatusLive()
|
||
}
|
||
},
|
||
onError = { msg ->
|
||
showBusy(false)
|
||
Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
|
||
showLoginThenDownload()
|
||
}
|
||
)
|
||
}
|
||
.setNegativeButton("Beenden") { _, _ -> finishAffinity() }
|
||
.create()
|
||
|
||
dialog.show()
|
||
}
|
||
|
||
private fun showBusy(show: Boolean) {
|
||
if (show) {
|
||
if (progress == null) {
|
||
progress = ProgressBar(this).apply {
|
||
isIndeterminate = true
|
||
(window?.decorView as? android.view.ViewGroup)?.addView(this)
|
||
}
|
||
}
|
||
progress?.visibility = View.VISIBLE
|
||
} else {
|
||
progress?.visibility = View.GONE
|
||
}
|
||
}
|
||
|
||
private fun dp(v: Int): Int = (v * resources.displayMetrics.density).toInt()
|
||
|
||
// --- LIVE NETZSTATUS (optional, für deine Status-Leiste) ---
|
||
override fun onResume() {
|
||
super.onResume()
|
||
registerNetworkCallback()
|
||
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
|
||
openingScreenHandler.refreshHeaderStatusLive()
|
||
}
|
||
}
|
||
|
||
override fun onPause() {
|
||
super.onPause()
|
||
unregisterNetworkCallback()
|
||
}
|
||
|
||
private fun registerNetworkCallback() {
|
||
if (netCb != null) return
|
||
val cm = getSystemService(ConnectivityManager::class.java)
|
||
val req = NetworkRequest.Builder()
|
||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||
.build()
|
||
netCb = object : ConnectivityManager.NetworkCallback() {
|
||
override fun onAvailable(network: Network) {
|
||
runOnUiThread {
|
||
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
|
||
openingScreenHandler.refreshHeaderStatusLive()
|
||
}
|
||
}
|
||
}
|
||
override fun onLost(network: Network) {
|
||
runOnUiThread {
|
||
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
|
||
openingScreenHandler.refreshHeaderStatusLive()
|
||
}
|
||
}
|
||
}
|
||
override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
|
||
runOnUiThread {
|
||
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
|
||
openingScreenHandler.refreshHeaderStatusLive()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
cm.registerNetworkCallback(req, netCb!!)
|
||
}
|
||
|
||
private fun unregisterNetworkCallback() {
|
||
val cb = netCb ?: return
|
||
val cm = getSystemService(ConnectivityManager::class.java)
|
||
cm.unregisterNetworkCallback(cb)
|
||
netCb = null
|
||
}
|
||
// --- /LIVE NETZSTATUS ---
|
||
|
||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||
super.onConfigurationChanged(newConfig)
|
||
}
|
||
|
||
fun startQuestionnaire(questionnaire: QuestionnaireBase<*>, languageID: String) {
|
||
isInQuestionnaire = true
|
||
isFirstQuestionnairePage = true
|
||
questionnaire.attach(this, languageID)
|
||
questionnaire.startQuestionnaire()
|
||
}
|
||
|
||
override fun onBackPressed() {
|
||
if (!::openingScreenHandler.isInitialized || !openingScreenHandler.onBackPressed()) {
|
||
super.onBackPressed()
|
||
}
|
||
}
|
||
|
||
fun finishQuestionnaire() {
|
||
isInQuestionnaire = false
|
||
isFirstQuestionnairePage = false
|
||
if (::openingScreenHandler.isInitialized) {
|
||
openingScreenHandler.init()
|
||
}
|
||
}
|
||
}
|