android, desktop: show alerts on critical and internal errors

This commit is contained in:
Avently 2024-01-06 03:43:56 +07:00
parent bb61b9c658
commit 60357d271a
7 changed files with 85 additions and 5 deletions

View File

@ -122,6 +122,9 @@ object ChatModel {
val remoteHostPairing = mutableStateOf<Pair<RemoteHostInfo?, RemoteHostSessionState>?>(null)
val remoteCtrlSession = mutableStateOf<RemoteCtrlSession?>(null)
val processedCriticalError: ProcessedErrors<AgentErrorType.CRITICAL> = ProcessedErrors(60_000)
val processedInternalError: ProcessedErrors<AgentErrorType.INTERNAL> = ProcessedErrors(20_000)
fun getUser(userId: Long): User? = if (currentUser.value?.userId == userId) {
currentUser.value
} else {

View File

@ -108,6 +108,7 @@ class AppPreferences {
val chatArchiveTime = mkDatePreference(SHARED_PREFS_CHAT_ARCHIVE_TIME, null)
val chatLastStart = mkDatePreference(SHARED_PREFS_CHAT_LAST_START, null)
val developerTools = mkBoolPreference(SHARED_PREFS_DEVELOPER_TOOLS, false)
val showInternalErrors = mkBoolPreference(SHARED_PREFS_SHOW_INTERNAL_ERRORS, false)
val terminalAlwaysVisible = mkBoolPreference(SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE, false)
val networkUseSocksProxy = mkBoolPreference(SHARED_PREFS_NETWORK_USE_SOCKS_PROXY, false)
val networkProxyHostPort = mkStrPreference(SHARED_PREFS_NETWORK_PROXY_HOST_PORT, "localhost:9050")
@ -276,6 +277,7 @@ class AppPreferences {
private const val SHARED_PREFS_ONBOARDING_STAGE = "OnboardingStage"
private const val SHARED_PREFS_CHAT_LAST_START = "ChatLastStart"
private const val SHARED_PREFS_DEVELOPER_TOOLS = "DeveloperTools"
private const val SHARED_PREFS_SHOW_INTERNAL_ERRORS = "ShowInternalErrors"
private const val SHARED_PREFS_TERMINAL_ALWAYS_VISIBLE = "TerminalAlwaysVisible"
private const val SHARED_PREFS_NETWORK_USE_SOCKS_PROXY = "NetworkUseSocksProxy"
private const val SHARED_PREFS_NETWORK_PROXY_HOST_PORT = "NetworkProxyHostPort"
@ -1920,6 +1922,14 @@ object ChatController {
}
}
}
is CR.ChatCmdError -> when {
r.chatError is ChatError.ChatErrorAgent && r.chatError.agentError is AgentErrorType.CRITICAL -> {
chatModel.processedCriticalError.newError(r.chatError.agentError, r.chatError.agentError.offerRestart)
}
r.chatError is ChatError.ChatErrorAgent && r.chatError.agentError is AgentErrorType.INTERNAL && appPrefs.showInternalErrors.get() -> {
chatModel.processedInternalError.newError(r.chatError.agentError, false)
}
}
else ->
Log.d(TAG , "unsupported event: ${r.responseType}")
}
@ -4710,6 +4720,7 @@ sealed class AgentErrorType {
is AGENT -> "AGENT ${agentErr.string}"
is INTERNAL -> "INTERNAL $internalErr"
is INACTIVE -> "INACTIVE"
is CRITICAL -> "CRITICAL $offerRestart $criticalErr"
}
@Serializable @SerialName("CMD") class CMD(val cmdErr: CommandErrorType): AgentErrorType()
@Serializable @SerialName("CONN") class CONN(val connErr: ConnectionErrorType): AgentErrorType()
@ -4721,6 +4732,7 @@ sealed class AgentErrorType {
@Serializable @SerialName("AGENT") class AGENT(val agentErr: SMPAgentError): AgentErrorType()
@Serializable @SerialName("INTERNAL") class INTERNAL(val internalErr: String): AgentErrorType()
@Serializable @SerialName("INACTIVE") object INACTIVE: AgentErrorType()
@Serializable @SerialName("CRITICAL") data class CRITICAL(val offerRestart: Boolean, val criticalErr: String): AgentErrorType()
}
@Serializable

View File

@ -407,6 +407,12 @@ private fun stopChatAlert(m: ChatModel) {
)
}
fun restartChatAlert() {
authStopChat(chatModel) {
startChat(chatModel, mutableStateOf(Instant.DISTANT_PAST), chatModel.chatDbChanged)
}
}
private fun exportProhibitedAlert() {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.set_password_to_export),
@ -414,7 +420,7 @@ private fun exportProhibitedAlert() {
)
}
private fun authStopChat(m: ChatModel) {
private fun authStopChat(m: ChatModel, onStop: (() -> Unit)? = null) {
if (m.controller.appPrefs.performLA.get()) {
authenticate(
generalGetString(MR.strings.auth_stop_chat),
@ -422,7 +428,7 @@ private fun authStopChat(m: ChatModel) {
completed = { laResult ->
when (laResult) {
LAResult.Success, is LAResult.Unavailable -> {
stopChat(m)
stopChat(m, onStop)
}
is LAResult.Error -> {
m.chatRunning.value = true
@ -434,15 +440,16 @@ private fun authStopChat(m: ChatModel) {
}
)
} else {
stopChat(m)
stopChat(m, onStop)
}
}
private fun stopChat(m: ChatModel) {
private fun stopChat(m: ChatModel, onStop: (() -> Unit)? = null) {
withApi {
try {
stopChatAsync(m)
platform.androidChatStopped()
onStop?.invoke()
} catch (e: Error) {
m.chatRunning.value = true
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_stopping_chat), e.toString())

View File

@ -0,0 +1,47 @@
package chat.simplex.common.views.helpers
import chat.simplex.common.model.AgentErrorType
import chat.simplex.common.views.database.restartChatAlert
import chat.simplex.res.MR
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlin.math.max
class ProcessedErrors <T: AgentErrorType>(val interval: Long) {
private var lastShownTimestamp: Long = System.currentTimeMillis() - interval
private var lastShownOfferRestart: Boolean = false
private var timer: Job = Job()
fun newError(error: T, offerRestart: Boolean) {
timer.cancel()
val job = withBGApi {
if (lastShownOfferRestart || !offerRestart) {
delay(max((lastShownTimestamp + interval) - System.currentTimeMillis(), 0))
}
lastShownTimestamp = System.currentTimeMillis()
lastShownOfferRestart = offerRestart
AlertManager.shared.hideAllAlerts()
when (error) {
is AgentErrorType.CRITICAL -> {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.agent_critical_error_title),
text = generalGetString(MR.strings.agent_critical_error_desc).format(error.criticalErr),
confirmText = if (offerRestart) generalGetString(MR.strings.restart_chat_button) else generalGetString(MR.strings.ok),
onConfirm = {
if (offerRestart) {
withApi { restartChatAlert() }
}
}
)
}
is AgentErrorType.INTERNAL -> {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.agent_internal_error_title),
text = generalGetString(MR.strings.agent_internal_error_desc).format(error.internalErr),
)
}
}
}
timer = job
}
}

View File

@ -10,10 +10,11 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import chat.simplex.common.model.*
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.appPlatform
import chat.simplex.common.platform.appPreferences
import chat.simplex.common.views.TerminalView
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
@ -44,6 +45,7 @@ fun DeveloperView(
m.controller.appPrefs.terminalAlwaysVisible.set(false)
}
}
SettingsPreferenceItem(painterResource(MR.images.ic_report), stringResource(MR.strings.show_internal_errors), appPreferences.showInternalErrors)
}
}
SectionTextFooter(

View File

@ -662,6 +662,7 @@
<string name="hide_dev_options">Hide:</string>
<string name="show_developer_options">Show developer options</string>
<string name="developer_options">Database IDs and Transport isolation option.</string>
<string name="show_internal_errors">Show internal errors</string>
<string name="shutdown_alert_question">Shutdown?</string>
<string name="shutdown_alert_desc">Notifications will stop working until you re-launch the app</string>
@ -1724,4 +1725,11 @@
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">You are already joining the group via this link.</string>
<string name="connect_plan_you_are_already_in_group_vName">You are already in group %1$s.</string>
<string name="connect_plan_connect_via_link">Connect via link?</string>
<!-- Errors -->
<string name="agent_critical_error_title">Critical error</string>
<string name="agent_critical_error_desc">Critical problem occurred with message delivery. Report the issue to the app developers: \n%s\n\nYou can restart the chat to repeat the failed process.</string>
<string name="agent_internal_error_title">Internal error</string>
<string name="agent_internal_error_desc">Internal problem occurred with message delivery. Report the issue to the app developers: \n%s</string>
<string name="restart_chat_button">Restart chat</string>
</resources>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M479.895-284Q494-284 504-293.895q10-9.894 10-24Q514-332 504.105-342q-9.894-10-24-10Q466-352 456-342.105q-10 9.894-10 24Q446-304 455.895-294q9.894 10 24 10ZM451.5-425H509v-261h-57.5v261ZM332-124.5 124.5-332.176V-628l207.676-207.5H628l207.5 207.676V-332L627.824-124.5H332Zm24.222-57.5h248.243L778-356.222v-248.243L604.242-778H356L182-604.242V-356l174.222 174ZM480-480Z"/></svg>

After

Width:  |  Height:  |  Size: 472 B