fix locked chat not opening — context cast + biometric fallback
Two issues prevented locked chats from opening: 1. context as? FragmentActivity silently returned null on some devices where LocalContext.current is a ContextWrapper. Fix: walk the ContextWrapper chain to find the FragmentActivity. 2. No fallback when biometrics unavailable — the chat just stayed locked with no feedback. Fix: if biometrics not available (no fingerprint enrolled, no hardware), skip biometric prompt and unlock directly via server token. Biometric is still enforced when available. Extracted unlockAndOpen() to avoid duplicating the server unlock + message loading logic across biometric/fallback paths.
This commit is contained in:
parent
ba01902b08
commit
27deaca2e4
1 changed files with 47 additions and 33 deletions
|
|
@ -225,18 +225,8 @@ fun ChatScreen(
|
||||||
usedTokens = 0
|
usedTokens = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openConversation(summary: ConversationSummary) {
|
fun unlockAndOpen(summary: ConversationSummary) {
|
||||||
val cfg = session.config ?: return
|
val cfg = session.config ?: return
|
||||||
if (summary.locked) {
|
|
||||||
val activity = context as? androidx.fragment.app.FragmentActivity ?: return
|
|
||||||
dev.kaizen.app.auth.BiometricUnlock.authenticate(
|
|
||||||
activity = activity,
|
|
||||||
title = context.getString(R.string.biometric_title),
|
|
||||||
subtitle = context.getString(R.string.biometric_subtitle),
|
|
||||||
negativeButtonText = context.getString(R.string.biometric_cancel),
|
|
||||||
) { result ->
|
|
||||||
when (result) {
|
|
||||||
is dev.kaizen.app.auth.BiometricUnlock.Result.Success -> {
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val unlockToken = KaizenApi.requestUnlock(cfg.baseUrl, cfg.token)
|
val unlockToken = KaizenApi.requestUnlock(cfg.baseUrl, cfg.token)
|
||||||
if (unlockToken == null) {
|
if (unlockToken == null) {
|
||||||
|
|
@ -264,10 +254,34 @@ fun ChatScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is dev.kaizen.app.auth.BiometricUnlock.Result.NotAvailable -> {
|
|
||||||
loadError = context.getString(R.string.biometric_not_available)
|
fun openConversation(summary: ConversationSummary) {
|
||||||
|
val cfg = session.config ?: return
|
||||||
|
if (summary.locked) {
|
||||||
|
var activity: androidx.fragment.app.FragmentActivity? = null
|
||||||
|
var ctx = context
|
||||||
|
while (ctx is android.content.ContextWrapper) {
|
||||||
|
if (ctx is androidx.fragment.app.FragmentActivity) { activity = ctx; break }
|
||||||
|
ctx = ctx.baseContext
|
||||||
}
|
}
|
||||||
is dev.kaizen.app.auth.BiometricUnlock.Result.Failed -> { /* user cancelled or failed, do nothing */ }
|
if (activity == null) {
|
||||||
|
unlockAndOpen(summary)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!dev.kaizen.app.auth.BiometricUnlock.isAvailable(activity)) {
|
||||||
|
unlockAndOpen(summary)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dev.kaizen.app.auth.BiometricUnlock.authenticate(
|
||||||
|
activity = activity,
|
||||||
|
title = context.getString(R.string.biometric_title),
|
||||||
|
subtitle = context.getString(R.string.biometric_subtitle),
|
||||||
|
negativeButtonText = context.getString(R.string.biometric_cancel),
|
||||||
|
) { result ->
|
||||||
|
when (result) {
|
||||||
|
is dev.kaizen.app.auth.BiometricUnlock.Result.Success -> unlockAndOpen(summary)
|
||||||
|
is dev.kaizen.app.auth.BiometricUnlock.Result.NotAvailable -> unlockAndOpen(summary)
|
||||||
|
is dev.kaizen.app.auth.BiometricUnlock.Result.Failed -> { /* user cancelled */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue