added dummy accounts, change passwort is now a feature, toast when session takes to long, online frontend fix
This commit is contained in:
@ -25,19 +25,6 @@ object DatabaseUploader {
|
||||
|
||||
private val client = OkHttpClient()
|
||||
|
||||
fun uploadDatabaseWithLogin(context: Context, username: String, password: String) {
|
||||
LoginManager.loginUserWithCredentials(
|
||||
context = context,
|
||||
username = username,
|
||||
password = password,
|
||||
onSuccess = { token ->
|
||||
Log.d("UPLOAD", "Login OK (user=$username)")
|
||||
uploadDatabase(context, token)
|
||||
},
|
||||
onError = { msg -> Log.e("UPLOAD", "Login fehlgeschlagen: $msg") }
|
||||
)
|
||||
}
|
||||
|
||||
private fun uploadDatabase(context: Context, token: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
@ -171,6 +158,8 @@ object DatabaseUploader {
|
||||
}
|
||||
|
||||
fun uploadDatabaseWithToken(context: Context, token: String) {
|
||||
uploadDatabase(context, token) // nutzt die bestehende interne Logik
|
||||
uploadDatabase(context, token)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -13,6 +13,8 @@ import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
|
||||
var RHS_POINTS: Int? = null
|
||||
|
||||
@ -32,6 +34,8 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
private lateinit var databaseButton: Button
|
||||
private lateinit var statusSession: TextView
|
||||
private lateinit var statusOnline: TextView
|
||||
private val SESSION_WARN_AFTER_MS = 12 * 60 * 60 * 1000L // 12h
|
||||
private var sessionLongWarnedOnce = false
|
||||
|
||||
private val dynamicButtons = mutableListOf<Button>()
|
||||
private val questionnaireFiles = mutableMapOf<Button, String>()
|
||||
@ -63,6 +67,11 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
|
||||
fun init() {
|
||||
activity.setContentView(R.layout.opening_screen)
|
||||
|
||||
// <<< NEU: bei jedem Öffnen des Screens zurücksetzen,
|
||||
// damit der Toast pro Besuch einmal angezeigt wird
|
||||
sessionLongWarnedOnce = false
|
||||
|
||||
bindViews()
|
||||
loadQuestionnaireOrder()
|
||||
createQuestionnaireButtons()
|
||||
@ -82,9 +91,14 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
|
||||
val pathExists = File("/data/data/com.dano.test1/databases/questionnaire_database").exists()
|
||||
updateMainButtonsState(pathExists)
|
||||
updateDownloadButtonState(pathExists) // <<< NEU: Download-Button anhand DB-Status setzen
|
||||
updateDownloadButtonState(pathExists)
|
||||
|
||||
if (pathExists && !editText.text.isNullOrBlank()) buttonLoad.performClick()
|
||||
|
||||
uiHandler.removeCallbacks(statusTicker)
|
||||
updateStatusStrip()
|
||||
applySessionAgeHighlight(System.currentTimeMillis() - TokenStore.getLoginTimestamp(activity))
|
||||
uiHandler.post(statusTicker)
|
||||
}
|
||||
|
||||
private fun bindViews() {
|
||||
@ -97,7 +111,10 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
saveButton = activity.findViewById(R.id.saveButton)
|
||||
editButton = activity.findViewById(R.id.editButton)
|
||||
uploadButton = activity.findViewById(R.id.uploadButton)
|
||||
|
||||
downloadButton = activity.findViewById(R.id.downloadButton)
|
||||
downloadButton.visibility = View.GONE
|
||||
|
||||
databaseButton = activity.findViewById(R.id.databaseButton)
|
||||
statusSession = activity.findViewById(R.id.statusSession)
|
||||
statusOnline = activity.findViewById(R.id.statusOnline)
|
||||
@ -444,53 +461,50 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
private fun setupUploadButton() {
|
||||
uploadButton.text = t("upload")
|
||||
uploadButton.setOnClickListener {
|
||||
// 1) Token-Frische prüfen (24h Gültigkeit; wir nehmen 23h als Puffer)
|
||||
val existingToken = TokenStore.getToken(activity)
|
||||
val ageMs = System.currentTimeMillis() - TokenStore.getLoginTimestamp(activity)
|
||||
val isFresh = !existingToken.isNullOrBlank() && ageMs < 23 * 60 * 60 * 1000
|
||||
// ZUERST bestätigen lassen
|
||||
confirmUpload {
|
||||
// === dein bestehender Upload-Code unverändert ===
|
||||
val existingToken = TokenStore.getToken(activity)
|
||||
val ageMs = System.currentTimeMillis() - TokenStore.getLoginTimestamp(activity)
|
||||
val isFresh = !existingToken.isNullOrBlank() && ageMs < 23 * 60 * 60 * 1000
|
||||
|
||||
if (isFresh) {
|
||||
// Frischer Token -> direkt hochladen
|
||||
GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim()
|
||||
DatabaseUploader.uploadDatabaseWithToken(activity, existingToken!!)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
// 2) Kein/alter Token -> Login anstoßen
|
||||
val username = TokenStore.getUsername(activity)?.trim().orEmpty()
|
||||
if (username.isBlank()) {
|
||||
Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
// *** NUR für deine Testumgebung: bekannte Passwörter ableiten ***
|
||||
// user01 -> pw1, user02 -> pw2 (entspricht login.php)
|
||||
val password = when (username) {
|
||||
"user01" -> "pw1"
|
||||
"user02" -> "pw2"
|
||||
else -> {
|
||||
Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
|
||||
// Re-Login -> neuen Token speichern -> Upload starten
|
||||
LoginManager.loginUserWithCredentials(
|
||||
context = activity,
|
||||
username = username,
|
||||
password = password,
|
||||
onSuccess = { freshToken ->
|
||||
if (isFresh) {
|
||||
GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim()
|
||||
DatabaseUploader.uploadDatabaseWithToken(activity, freshToken)
|
||||
},
|
||||
onError = { msg ->
|
||||
Toast.makeText(activity, t("login_failed_with_reason").replace("{reason}", msg), Toast.LENGTH_LONG).show()
|
||||
DatabaseUploader.uploadDatabaseWithToken(activity, existingToken!!)
|
||||
return@confirmUpload
|
||||
}
|
||||
)
|
||||
|
||||
val username = TokenStore.getUsername(activity)?.trim().orEmpty()
|
||||
if (username.isBlank()) {
|
||||
Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
|
||||
return@confirmUpload
|
||||
}
|
||||
|
||||
val password = when (username) {
|
||||
"user01" -> "pw1"
|
||||
"user02" -> "pw2"
|
||||
else -> {
|
||||
Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
|
||||
return@confirmUpload
|
||||
}
|
||||
}
|
||||
|
||||
LoginManager.loginUserWithCredentials(
|
||||
context = activity,
|
||||
username = username,
|
||||
password = password,
|
||||
onSuccess = { freshToken ->
|
||||
GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim()
|
||||
DatabaseUploader.uploadDatabaseWithToken(activity, freshToken)
|
||||
},
|
||||
onError = { msg ->
|
||||
Toast.makeText(activity, t("login_failed_with_reason").replace("{reason}", msg), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setupDownloadButton() {
|
||||
downloadButton.text = t("download")
|
||||
|
||||
@ -522,7 +536,6 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
// Der Download-Button wird separat gesteuert
|
||||
}
|
||||
|
||||
/** <<< NEU: Steuert Aktivierung & Look des Download-Buttons je nach DB-Verfügbarkeit */
|
||||
private fun updateDownloadButtonState(isDatabaseAvailable: Boolean) {
|
||||
val mb = downloadButton as? MaterialButton
|
||||
if (isDatabaseAvailable) {
|
||||
@ -619,13 +632,18 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
val h = TimeUnit.MILLISECONDS.toHours(ageMs)
|
||||
val m = TimeUnit.MILLISECONDS.toMinutes(ageMs) - h * 60
|
||||
if (ts > 0L) {
|
||||
statusSession.text = "${t("session_label")}: ${h}${t("hours_short")} ${m}${t("minutes_short")}"
|
||||
// ⚠️ anhängen, wenn >12h, der eigentliche Hinweis/Styling kommt aus applySessionAgeHighlight()
|
||||
val warn = if (ageMs >= SESSION_WARN_AFTER_MS) " ⚠️" else ""
|
||||
statusSession.text = "${t("session_label")}: ${h}${t("hours_short")} ${m}${t("minutes_short")}$warn"
|
||||
} else {
|
||||
statusSession.text = t("session_dash")
|
||||
}
|
||||
val online = NetworkUtils.isOnline(activity)
|
||||
statusOnline.text = if (online) t("online") else t("offline")
|
||||
statusOnline.setTextColor(if (online) Color.parseColor("#2E7D32") else Color.parseColor("#C62828"))
|
||||
|
||||
// <<< NEU: hier jeweils prüfen/markieren
|
||||
applySessionAgeHighlight(ageMs)
|
||||
}
|
||||
|
||||
fun refreshHeaderStatusLive() {
|
||||
@ -644,4 +662,58 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
coachEditText.compoundDrawablePadding = dp(8)
|
||||
coachEditText.alpha = 0.95f
|
||||
}
|
||||
|
||||
private fun applySessionAgeHighlight(ageMs: Long) {
|
||||
val isOld = ageMs >= SESSION_WARN_AFTER_MS
|
||||
if (isOld) {
|
||||
statusSession.setTextColor(Color.parseColor("#C62828"))
|
||||
statusSession.setBackgroundColor(Color.parseColor("#FFF3CD"))
|
||||
statusSession.setPadding(dp(8), dp(4), dp(8), dp(4))
|
||||
if (!sessionLongWarnedOnce) {
|
||||
showRedToast(activity, t("session_over_12"))
|
||||
sessionLongWarnedOnce = true
|
||||
}
|
||||
} else {
|
||||
statusSession.setTextColor(Color.parseColor("#2F2A49"))
|
||||
statusSession.setBackgroundColor(Color.TRANSPARENT)
|
||||
statusSession.setPadding(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun showRedToast(ctx: android.content.Context, message: String) {
|
||||
val tv = android.widget.TextView(ctx).apply {
|
||||
text = message
|
||||
setTextColor(android.graphics.Color.WHITE)
|
||||
textSize = 16f
|
||||
setPadding(32, 20, 32, 20)
|
||||
background = android.graphics.drawable.GradientDrawable().apply {
|
||||
shape = android.graphics.drawable.GradientDrawable.RECTANGLE
|
||||
cornerRadius = 24f
|
||||
setColor(android.graphics.Color.parseColor("#D32F2F")) // kräftiges Rot
|
||||
}
|
||||
}
|
||||
android.widget.Toast(ctx).apply {
|
||||
duration = android.widget.Toast.LENGTH_LONG
|
||||
view = tv
|
||||
setGravity(android.view.Gravity.TOP or android.view.Gravity.CENTER_HORIZONTAL, 0, 120)
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun confirmUpload(onConfirm: () -> Unit) {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(t("start_upload"))
|
||||
.setMessage(t("ask_before_upload"))
|
||||
.setPositiveButton(t("ok")) { d, _ ->
|
||||
d.dismiss()
|
||||
onConfirm()
|
||||
}
|
||||
.setNegativeButton(t("cancel")) { d, _ ->
|
||||
d.dismiss()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -400,7 +400,12 @@ object LanguageManager {
|
||||
"done" to "Erledigt",
|
||||
"not_done" to "Nicht erledigt",
|
||||
"none" to "Keine",
|
||||
"view_missing" to "Fehlende View: %s"
|
||||
"view_missing" to "Fehlende View: %s",
|
||||
"session_over_12" to "Sitzung läuft länger als 12 Stunden.",
|
||||
"cancel" to "Cancel",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Möchtest du den Upload wirklich ausführen?",
|
||||
"start_upload" to "Upload starten?"
|
||||
),
|
||||
|
||||
"ENGLISH" to mapOf(
|
||||
@ -771,7 +776,12 @@ object LanguageManager {
|
||||
"done" to "Done",
|
||||
"not_done" to "Not done",
|
||||
"none" to "None",
|
||||
"view_missing" to "Missing view: %s"
|
||||
"view_missing" to "Missing view: %s",
|
||||
"session_over_12" to "Session has been running for more than 12 hours.",
|
||||
"cancel" to "Cancel",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Do you really want to perform the upload?",
|
||||
"start_upload" to "Start upload?"
|
||||
),
|
||||
|
||||
"FRENCH" to mapOf(
|
||||
@ -1146,7 +1156,12 @@ object LanguageManager {
|
||||
"done" to "Terminé",
|
||||
"not_done" to "Non terminé",
|
||||
"none" to "Aucun",
|
||||
"view_missing" to "Vue manquante : %s"
|
||||
"view_missing" to "Vue manquante : %s",
|
||||
"session_over_12" to "La session dure depuis plus de 12 heures.",
|
||||
"cancel" to "Annuler",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Voulez-vous vraiment effectuer le téléversement ?",
|
||||
"start_upload" to "Démarrer le téléversement ?"
|
||||
),
|
||||
|
||||
"RUSSIAN" to mapOf(
|
||||
@ -1517,7 +1532,12 @@ object LanguageManager {
|
||||
"done" to "Готово",
|
||||
"not_done" to "Не выполнено",
|
||||
"none" to "Нет",
|
||||
"view_missing" to "Отсутствует представление: %s"
|
||||
"view_missing" to "Отсутствует представление: %s",
|
||||
"session_over_12" to "Сеанс продолжается более 12 часов.",
|
||||
"cancel" to "Отмена",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Вы действительно хотите выполнить загрузку?",
|
||||
"start_upload" to "Начать загрузку?"
|
||||
),
|
||||
|
||||
"UKRAINIAN" to mapOf(
|
||||
@ -1892,7 +1912,12 @@ object LanguageManager {
|
||||
"done" to "Готово",
|
||||
"not_done" to "Не виконано",
|
||||
"none" to "Немає",
|
||||
"view_missing" to "Відсутній елемент інтерфейсу: %s"
|
||||
"view_missing" to "Відсутній елемент інтерфейсу: %s",
|
||||
"session_over_12" to "Сеанс триває понад 12 годин.",
|
||||
"cancel" to "Скасувати",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Ви справді хочете виконати завантаження?",
|
||||
"start_upload" to "Почати завантаження?"
|
||||
),
|
||||
|
||||
"TURKISH" to mapOf(
|
||||
@ -2267,7 +2292,12 @@ object LanguageManager {
|
||||
"done" to "Tamamlandı",
|
||||
"not_done" to "Tamamlanmadı",
|
||||
"none" to "Yok",
|
||||
"view_missing" to "Eksik görünüm: %s"
|
||||
"view_missing" to "Eksik görünüm: %s",
|
||||
"session_over_12" to "Oturum 12 saatten uzun süredir açık.",
|
||||
"cancel" to "İptal",
|
||||
"ok" to "Tamam",
|
||||
"ask_before_upload" to "Yüklemeyi gerçekten yapmak istiyor musunuz?",
|
||||
"start_upload" to "Yüklemeyi başlat?"
|
||||
),
|
||||
|
||||
"POLISH" to mapOf(
|
||||
@ -2642,7 +2672,12 @@ object LanguageManager {
|
||||
"done" to "Zrobione",
|
||||
"not_done" to "Niezrobione",
|
||||
"none" to "Brak",
|
||||
"view_missing" to "Brak widoku: %s"
|
||||
"view_missing" to "Brak widoku: %s",
|
||||
"session_over_12" to "Sesja trwa dłużej niż 12 godzin.",
|
||||
"cancel" to "Anuluj",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Czy na pewno chcesz wykonać przesyłanie?",
|
||||
"start_upload" to "Rozpocząć przesyłanie?"
|
||||
),
|
||||
|
||||
"ARABIC" to mapOf(
|
||||
@ -3017,7 +3052,12 @@ object LanguageManager {
|
||||
"done" to "منجز",
|
||||
"not_done" to "غير منجز",
|
||||
"none" to "لا شيء",
|
||||
"view_missing" to "العنصر المفقود: %s"
|
||||
"view_missing" to "العنصر المفقود: %s",
|
||||
"session_over_12" to "تعمل الجلسة منذ أكثر من 12 ساعة.",
|
||||
"cancel" to "إلغاء",
|
||||
"ok" to "موافق",
|
||||
"ask_before_upload" to "هل ترغب فعلًا في تنفيذ الرفع؟",
|
||||
"start_upload" to "بدء الرفع؟"
|
||||
),
|
||||
|
||||
"ROMANIAN" to mapOf(
|
||||
@ -3392,7 +3432,12 @@ object LanguageManager {
|
||||
"done" to "Finalizat",
|
||||
"not_done" to "Nefinalizat",
|
||||
"none" to "Nimic",
|
||||
"view_missing" to "Vizualizare lipsă: %s"
|
||||
"view_missing" to "Vizualizare lipsă: %s",
|
||||
"session_over_12" to "Sesiunea rulează de mai bine de 12 ore.",
|
||||
"cancel" to "Anulează",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "Vrei într-adevăr să efectuezi încărcarea?",
|
||||
"start_upload" to "Pornești încărcarea?"
|
||||
),
|
||||
|
||||
"SPANISH" to mapOf(
|
||||
@ -3767,7 +3812,12 @@ object LanguageManager {
|
||||
"done" to "Completado",
|
||||
"not_done" to "No completado",
|
||||
"none" to "Ninguno",
|
||||
"view_missing" to "Vista faltante: %s"
|
||||
"view_missing" to "Vista faltante: %s",
|
||||
"session_over_12" to "La sesión lleva más de 12 horas.",
|
||||
"cancel" to "Cancelar",
|
||||
"ok" to "OK",
|
||||
"ask_before_upload" to "¿Realmente deseas realizar la carga?",
|
||||
"start_upload" to "¿Iniciar la carga?"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package com.dano.test1
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
@ -14,6 +16,7 @@ import org.json.JSONObject
|
||||
|
||||
object LoginManager {
|
||||
private const val SERVER_LOGIN_URL = "https://daniel-ocks.de/qdb/login.php"
|
||||
private const val SERVER_CHANGE_URL = "https://daniel-ocks.de/qdb/change_password.php"
|
||||
private val client = OkHttpClient()
|
||||
|
||||
fun loginUserWithCredentials(
|
||||
@ -39,23 +42,177 @@ object LoginManager {
|
||||
val response = client.newCall(request).execute()
|
||||
val text = response.body?.string()
|
||||
|
||||
if (response.isSuccessful && text != null) {
|
||||
val json = JSONObject(text)
|
||||
if (json.optBoolean("success")) {
|
||||
val token = json.getString("token")
|
||||
// => setzt auch den Login-Timestamp:
|
||||
TokenStore.save(context, token, username)
|
||||
withContext(Dispatchers.Main) { onSuccess(token) }
|
||||
} else {
|
||||
withContext(Dispatchers.Main) { onError("Login fehlgeschlagen") }
|
||||
}
|
||||
} else {
|
||||
if (!response.isSuccessful || text == null) {
|
||||
withContext(Dispatchers.Main) { onError("Fehler beim Login (${response.code})") }
|
||||
return@launch
|
||||
}
|
||||
|
||||
val json = JSONObject(text)
|
||||
if (!json.optBoolean("success")) {
|
||||
withContext(Dispatchers.Main) { onError(json.optString("message", "Login fehlgeschlagen")) }
|
||||
return@launch
|
||||
}
|
||||
|
||||
// Passwortwechsel erforderlich?
|
||||
if (json.optBoolean("must_change_password", false)) {
|
||||
withContext(Dispatchers.Main) {
|
||||
showChangePasswordDialog(
|
||||
context = context,
|
||||
username = username,
|
||||
oldPassword = password,
|
||||
onChanged = { token ->
|
||||
// Nach PW-Änderung direkt eingeloggt
|
||||
TokenStore.save(context, token, username)
|
||||
onSuccess(token)
|
||||
},
|
||||
onError = onError
|
||||
)
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
|
||||
// normaler Login: Token speichern
|
||||
val token = json.getString("token")
|
||||
TokenStore.save(context, token, username)
|
||||
withContext(Dispatchers.Main) { onSuccess(token) }
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("LOGIN", "Exception", e)
|
||||
withContext(Dispatchers.Main) { onError("Exception: ${e.message}") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showChangePasswordDialog(
|
||||
context: Context,
|
||||
username: String,
|
||||
oldPassword: String,
|
||||
onChanged: (String) -> Unit,
|
||||
onError: (String) -> Unit
|
||||
) {
|
||||
val container = LinearLayout(context).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding(48, 24, 48, 0)
|
||||
}
|
||||
val etNew = EditText(context).apply {
|
||||
hint = "Neues Passwort"
|
||||
inputType = android.text.InputType.TYPE_CLASS_TEXT or
|
||||
android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||
}
|
||||
val etRepeat = EditText(context).apply {
|
||||
hint = "Neues Passwort (wiederholen)"
|
||||
inputType = android.text.InputType.TYPE_CLASS_TEXT or
|
||||
android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||
}
|
||||
container.addView(etNew)
|
||||
container.addView(etRepeat)
|
||||
|
||||
val dialog = AlertDialog.Builder(context)
|
||||
.setTitle("Passwort ändern")
|
||||
.setMessage("Du verwendest ein Standard-Konto. Bitte setze jetzt ein eigenes Passwort.")
|
||||
.setView(container)
|
||||
.setPositiveButton("OK", null) // nicht sofort schließen lassen
|
||||
.setNegativeButton("Abbrechen", null) // nicht sofort schließen lassen
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
|
||||
dialog.setOnShowListener {
|
||||
val btnOk = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||
val btnCancel = dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
||||
|
||||
btnOk.setOnClickListener {
|
||||
etNew.error = null
|
||||
etRepeat.error = null
|
||||
|
||||
val p1 = etNew.text?.toString().orEmpty()
|
||||
val p2 = etRepeat.text?.toString().orEmpty()
|
||||
|
||||
when {
|
||||
p1.length < 6 -> {
|
||||
etNew.error = "Mindestens 6 Zeichen."
|
||||
return@setOnClickListener
|
||||
}
|
||||
p1 != p2 -> {
|
||||
etRepeat.error = "Passwörter stimmen nicht überein."
|
||||
return@setOnClickListener
|
||||
}
|
||||
else -> {
|
||||
btnOk.isEnabled = false
|
||||
btnCancel.isEnabled = false
|
||||
changePassword(
|
||||
context = context,
|
||||
username = username,
|
||||
oldPassword = oldPassword,
|
||||
newPassword = p1,
|
||||
onChanged = { token ->
|
||||
dialog.dismiss()
|
||||
onChanged(token)
|
||||
},
|
||||
onError = { msg ->
|
||||
btnOk.isEnabled = true
|
||||
btnCancel.isEnabled = true
|
||||
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// >>> Überarbeitet: Abbrechen schließt Dialog und informiert den Aufrufer
|
||||
btnCancel.setOnClickListener {
|
||||
dialog.dismiss()
|
||||
onError("Passwortänderung abgebrochen.")
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun changePassword(
|
||||
context: Context,
|
||||
username: String,
|
||||
oldPassword: String,
|
||||
newPassword: String,
|
||||
onChanged: (String) -> Unit,
|
||||
onError: (String) -> Unit
|
||||
) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val body = JSONObject()
|
||||
.put("username", username)
|
||||
.put("old_password", oldPassword)
|
||||
.put("new_password", newPassword)
|
||||
.toString()
|
||||
.toRequestBody("application/json".toMediaType())
|
||||
|
||||
val req = Request.Builder()
|
||||
.url(SERVER_CHANGE_URL)
|
||||
.post(body)
|
||||
.build()
|
||||
|
||||
val resp = client.newCall(req).execute()
|
||||
val txt = resp.body?.string()
|
||||
|
||||
if (!resp.isSuccessful || txt == null) {
|
||||
withContext(Dispatchers.Main) { onError("Fehler beim Ändern (${resp.code})") }
|
||||
return@launch
|
||||
}
|
||||
|
||||
val json = JSONObject(txt)
|
||||
if (!json.optBoolean("success")) {
|
||||
withContext(Dispatchers.Main) { onError(json.optString("message", "Ändern fehlgeschlagen")) }
|
||||
return@launch
|
||||
}
|
||||
|
||||
val token = json.getString("token")
|
||||
withContext(Dispatchers.Main) { onChanged(token) }
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("LOGIN", "changePassword Exception", e)
|
||||
withContext(Dispatchers.Main) { onError("Exception: ${e.message}") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user