android, desktop: try-catch composables (#3575)
* android, desktop: try-catch composables
* test
* better catching on Android
* more try-catch'es
* Revert "test"
This reverts commit adaf92b116
.
* more try-catch'es
* unneeded imports
This commit is contained in:
parent
6ba3100d34
commit
4a4d470859
@ -1,6 +1,8 @@
|
|||||||
package chat.simplex.app
|
package chat.simplex.app
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import chat.simplex.common.platform.Log
|
import chat.simplex.common.platform.Log
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
@ -35,6 +37,21 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
registerGlobalErrorHandler()
|
registerGlobalErrorHandler()
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Looper.loop()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
if (e.message != null && e.message!!.startsWith("Unable to start activity")) {
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid())
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// Send it to our exception handled because it will not get the exception otherwise
|
||||||
|
Thread.getDefaultUncaughtExceptionHandler()?.uncaughtException(Looper.getMainLooper().thread, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
context = this
|
context = this
|
||||||
initHaskell()
|
initHaskell()
|
||||||
|
@ -4,7 +4,7 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Build
|
import android.os.*
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -12,7 +12,6 @@ import androidx.activity.compose.setContent
|
|||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import chat.simplex.common.AppScreen
|
import chat.simplex.common.AppScreen
|
||||||
import chat.simplex.common.ui.theme.SimpleXTheme
|
|
||||||
import chat.simplex.common.views.helpers.*
|
import chat.simplex.common.views.helpers.*
|
||||||
import androidx.compose.ui.platform.LocalContext as LocalContext1
|
import androidx.compose.ui.platform.LocalContext as LocalContext1
|
||||||
import chat.simplex.res.MR
|
import chat.simplex.res.MR
|
||||||
@ -79,6 +78,7 @@ actual fun androidIsFinishingMainActivity(): Boolean = (mainActivity.get()?.isFi
|
|||||||
actual class GlobalExceptionsHandler: Thread.UncaughtExceptionHandler {
|
actual class GlobalExceptionsHandler: Thread.UncaughtExceptionHandler {
|
||||||
actual override fun uncaughtException(thread: Thread, e: Throwable) {
|
actual override fun uncaughtException(thread: Thread, e: Throwable) {
|
||||||
Log.e(TAG, "App crashed, thread name: " + thread.name + ", exception: " + e.stackTraceToString())
|
Log.e(TAG, "App crashed, thread name: " + thread.name + ", exception: " + e.stackTraceToString())
|
||||||
|
includeMoreFailedComposables()
|
||||||
if (ModalManager.start.hasModalsOpen()) {
|
if (ModalManager.start.hasModalsOpen()) {
|
||||||
ModalManager.start.closeModal()
|
ModalManager.start.closeModal()
|
||||||
} else if (chatModel.chatId.value != null) {
|
} else if (chatModel.chatId.value != null) {
|
||||||
@ -93,19 +93,25 @@ actual class GlobalExceptionsHandler: Thread.UncaughtExceptionHandler {
|
|||||||
chatModel.callManager.endCall(it)
|
chatModel.callManager.endCall(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AlertManager.shared.showAlertMsg(
|
if (thread.name == "main") {
|
||||||
title = generalGetString(MR.strings.app_was_crashed),
|
mainActivity.get()?.recreate()
|
||||||
text = e.stackTraceToString()
|
} else {
|
||||||
)
|
mainActivity.get()?.apply {
|
||||||
//mainActivity.get()?.recreate()
|
window
|
||||||
mainActivity.get()?.apply {
|
?.decorView
|
||||||
window
|
?.findViewById<ViewGroup>(android.R.id.content)
|
||||||
?.decorView
|
?.removeViewAt(0)
|
||||||
?.findViewById<ViewGroup>(android.R.id.content)
|
setContent {
|
||||||
?.removeViewAt(0)
|
AppScreen()
|
||||||
setContent {
|
}
|
||||||
AppScreen()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Wait until activity recreates to prevent showing two alerts (in case `main` was crashed)
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
AlertManager.shared.showAlertMsg(
|
||||||
|
title = generalGetString(MR.strings.app_was_crashed),
|
||||||
|
text = e.stackTraceToString()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,9 +332,11 @@ fun DesktopScreen(settingsState: SettingsViewState) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
VerticalDivider(Modifier.padding(start = DEFAULT_START_MODAL_WIDTH))
|
VerticalDivider(Modifier.padding(start = DEFAULT_START_MODAL_WIDTH))
|
||||||
UserPicker(chatModel, userPickerState) {
|
tryOrShowError("UserPicker", error = {}) {
|
||||||
scope.launch { if (scaffoldState.drawerState.isOpen) scaffoldState.drawerState.close() else scaffoldState.drawerState.open() }
|
UserPicker(chatModel, userPickerState) {
|
||||||
userPickerState.value = AnimatedViewState.GONE
|
scope.launch { if (scaffoldState.drawerState.isOpen) scaffoldState.drawerState.close() else scaffoldState.drawerState.open() }
|
||||||
|
userPickerState.value = AnimatedViewState.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ModalManager.fullscreen.showInView()
|
ModalManager.fullscreen.showInView()
|
||||||
}
|
}
|
||||||
|
@ -900,7 +900,11 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatItemViewShortHand(cItem: ChatItem, range: IntRange?) {
|
fun ChatItemViewShortHand(cItem: ChatItem, range: IntRange?) {
|
||||||
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools)
|
tryOrShowError("${cItem.id}ChatItem", error = {
|
||||||
|
CIBrokenComposableView(if (cItem.chatDir.sent) Alignment.CenterEnd else Alignment.CenterStart)
|
||||||
|
}) {
|
||||||
|
ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, revealed = revealed, range = range, deleteMessage = deleteMessage, deleteMessages = deleteMessages, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package chat.simplex.common.views.chat.item
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.*
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import chat.simplex.res.MR
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CIBrokenComposableView(alignment: Alignment) {
|
||||||
|
Box(Modifier.fillMaxWidth().padding(horizontal = 10.dp, vertical = 6.dp), contentAlignment = alignment) {
|
||||||
|
Text(stringResource(MR.strings.error_showing_message), color = MaterialTheme.colors.error, fontStyle = FontStyle.Italic)
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@ -61,9 +62,17 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
is ChatInfo.Direct -> {
|
is ChatInfo.Direct -> {
|
||||||
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
|
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, stopped, linkMode, inProgress = false, progressByTimeout = false) },
|
chatLinkPreview = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||||
|
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, stopped, linkMode, inProgress = false, progressByTimeout = false)
|
||||||
|
}
|
||||||
|
},
|
||||||
click = { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) },
|
click = { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) },
|
||||||
dropdownMenuItems = { ContactMenuItems(chat, chat.chatInfo.contact, chatModel, showMenu, showMarkRead) },
|
dropdownMenuItems = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
|
||||||
|
ContactMenuItems(chat, chat.chatInfo.contact, chatModel, showMenu, showMarkRead)
|
||||||
|
}
|
||||||
|
},
|
||||||
showMenu,
|
showMenu,
|
||||||
stopped,
|
stopped,
|
||||||
selectedChat
|
selectedChat
|
||||||
@ -71,25 +80,45 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
}
|
}
|
||||||
is ChatInfo.Group ->
|
is ChatInfo.Group ->
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, stopped, linkMode, inProgress.value, progressByTimeout) },
|
chatLinkPreview = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||||
|
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, stopped, linkMode, inProgress.value, progressByTimeout)
|
||||||
|
}
|
||||||
|
},
|
||||||
click = { if (!inProgress.value) groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel, inProgress) },
|
click = { if (!inProgress.value) groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel, inProgress) },
|
||||||
dropdownMenuItems = { GroupMenuItems(chat, chat.chatInfo.groupInfo, chatModel, showMenu, inProgress, showMarkRead) },
|
dropdownMenuItems = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
|
||||||
|
GroupMenuItems(chat, chat.chatInfo.groupInfo, chatModel, showMenu, inProgress, showMarkRead)
|
||||||
|
}
|
||||||
|
},
|
||||||
showMenu,
|
showMenu,
|
||||||
stopped,
|
stopped,
|
||||||
selectedChat
|
selectedChat
|
||||||
)
|
)
|
||||||
is ChatInfo.ContactRequest ->
|
is ChatInfo.ContactRequest ->
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ContactRequestView(chat.chatInfo) },
|
chatLinkPreview = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||||
|
ContactRequestView(chat.chatInfo)
|
||||||
|
}
|
||||||
|
},
|
||||||
click = { contactRequestAlertDialog(chat.remoteHostId, chat.chatInfo, chatModel) },
|
click = { contactRequestAlertDialog(chat.remoteHostId, chat.chatInfo, chatModel) },
|
||||||
dropdownMenuItems = { ContactRequestMenuItems(chat.remoteHostId, chat.chatInfo, chatModel, showMenu) },
|
dropdownMenuItems = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
|
||||||
|
ContactRequestMenuItems(chat.remoteHostId, chat.chatInfo, chatModel, showMenu)
|
||||||
|
}
|
||||||
|
},
|
||||||
showMenu,
|
showMenu,
|
||||||
stopped,
|
stopped,
|
||||||
selectedChat
|
selectedChat
|
||||||
)
|
)
|
||||||
is ChatInfo.ContactConnection ->
|
is ChatInfo.ContactConnection ->
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = { ContactConnectionView(chat.chatInfo.contactConnection) },
|
chatLinkPreview = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||||
|
ContactConnectionView(chat.chatInfo.contactConnection)
|
||||||
|
}
|
||||||
|
},
|
||||||
click = {
|
click = {
|
||||||
ModalManager.center.closeModals()
|
ModalManager.center.closeModals()
|
||||||
ModalManager.end.closeModals()
|
ModalManager.end.closeModals()
|
||||||
@ -97,7 +126,11 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
ContactConnectionInfoView(chatModel, chat.remoteHostId, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close)
|
ContactConnectionInfoView(chatModel, chat.remoteHostId, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dropdownMenuItems = { ContactConnectionMenuItems(chat.remoteHostId, chat.chatInfo, chatModel, showMenu) },
|
dropdownMenuItems = {
|
||||||
|
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
|
||||||
|
ContactConnectionMenuItems(chat.remoteHostId, chat.chatInfo, chatModel, showMenu)
|
||||||
|
}
|
||||||
|
},
|
||||||
showMenu,
|
showMenu,
|
||||||
stopped,
|
stopped,
|
||||||
selectedChat
|
selectedChat
|
||||||
@ -105,7 +138,9 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
is ChatInfo.InvalidJSON ->
|
is ChatInfo.InvalidJSON ->
|
||||||
ChatListNavLinkLayout(
|
ChatListNavLinkLayout(
|
||||||
chatLinkPreview = {
|
chatLinkPreview = {
|
||||||
InvalidDataView()
|
tryOrShowError("${chat.id}ChatListNavLink", error = { ErrorChatListItem() }) {
|
||||||
|
InvalidDataView()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
click = {
|
click = {
|
||||||
ModalManager.end.closeModals()
|
ModalManager.end.closeModals()
|
||||||
@ -119,6 +154,13 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ErrorChatListItem() {
|
||||||
|
Box(Modifier.fillMaxWidth().padding(horizontal = 10.dp, vertical = 6.dp)) {
|
||||||
|
Text(stringResource(MR.strings.error_showing_content), color = MaterialTheme.colors.error, fontStyle = FontStyle.Italic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun directChatAction(rhId: Long?, contact: Contact, chatModel: ChatModel) {
|
fun directChatAction(rhId: Long?, contact: Contact, chatModel: ChatModel) {
|
||||||
when {
|
when {
|
||||||
contact.activeConn == null && contact.profile.contactLink != null -> askCurrentOrIncognitoProfileConnectContactViaAddress(chatModel, rhId, contact, close = null, openChat = true)
|
contact.activeConn == null && contact.profile.contactLink != null -> askCurrentOrIncognitoProfileConnectContactViaAddress(chatModel, rhId, contact, close = null, openChat = true)
|
||||||
|
@ -11,6 +11,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.*
|
import androidx.compose.ui.graphics.*
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
import dev.icerock.moko.resources.compose.painterResource
|
import dev.icerock.moko.resources.compose.painterResource
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@ -64,7 +65,11 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
|
|||||||
val (userPickerState, scaffoldState ) = settingsState
|
val (userPickerState, scaffoldState ) = settingsState
|
||||||
Scaffold(topBar = { Box(Modifier.padding(end = endPadding)) { ChatListToolbar(chatModel, scaffoldState.drawerState, userPickerState, stopped) { searchInList = it.trim() } } },
|
Scaffold(topBar = { Box(Modifier.padding(end = endPadding)) { ChatListToolbar(chatModel, scaffoldState.drawerState, userPickerState, stopped) { searchInList = it.trim() } } },
|
||||||
scaffoldState = scaffoldState,
|
scaffoldState = scaffoldState,
|
||||||
drawerContent = { SettingsView(chatModel, setPerformLA, scaffoldState.drawerState) },
|
drawerContent = {
|
||||||
|
tryOrShowError("Settings", error = { ErrorSettingsView() }) {
|
||||||
|
SettingsView(chatModel, setPerformLA, scaffoldState.drawerState)
|
||||||
|
}
|
||||||
|
},
|
||||||
drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
|
drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
|
||||||
drawerGesturesEnabled = appPlatform.isAndroid,
|
drawerGesturesEnabled = appPlatform.isAndroid,
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
@ -111,12 +116,16 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
|
|||||||
if (searchInList.isEmpty()) {
|
if (searchInList.isEmpty()) {
|
||||||
DesktopActiveCallOverlayLayout(newChatSheetState)
|
DesktopActiveCallOverlayLayout(newChatSheetState)
|
||||||
// TODO disable this button and sheet for the duration of the switch
|
// TODO disable this button and sheet for the duration of the switch
|
||||||
NewChatSheet(chatModel, newChatSheetState, stopped, hideNewChatSheet)
|
tryOrShowError("NewChatSheet", error = {}) {
|
||||||
|
NewChatSheet(chatModel, newChatSheetState, stopped, hideNewChatSheet)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (appPlatform.isAndroid) {
|
if (appPlatform.isAndroid) {
|
||||||
UserPicker(chatModel, userPickerState) {
|
tryOrShowError("UserPicker", error = {}) {
|
||||||
scope.launch { if (scaffoldState.drawerState.isOpen) scaffoldState.drawerState.close() else scaffoldState.drawerState.open() }
|
UserPicker(chatModel, userPickerState) {
|
||||||
userPickerState.value = AnimatedViewState.GONE
|
scope.launch { if (scaffoldState.drawerState.isOpen) scaffoldState.drawerState.close() else scaffoldState.drawerState.open() }
|
||||||
|
userPickerState.value = AnimatedViewState.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,6 +312,13 @@ fun connectIfOpenedViaUri(rhId: Long?, uri: URI, chatModel: ChatModel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ErrorSettingsView() {
|
||||||
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text(generalGetString(MR.strings.error_showing_content), color = MaterialTheme.colors.error, fontStyle = FontStyle.Italic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var lazyListState = 0 to 0
|
private var lazyListState = 0 to 0
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -47,10 +47,12 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (appPlatform.isAndroid) {
|
if (appPlatform.isAndroid) {
|
||||||
UserPicker(chatModel, userPickerState, showSettings = false, showCancel = true, cancelClicked = {
|
tryOrShowError("UserPicker", error = {}) {
|
||||||
chatModel.sharedContent.value = null
|
UserPicker(chatModel, userPickerState, showSettings = false, showCancel = true, cancelClicked = {
|
||||||
userPickerState.value = AnimatedViewState.GONE
|
chatModel.sharedContent.value = null
|
||||||
})
|
userPickerState.value = AnimatedViewState.GONE
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,6 +390,28 @@ fun IntSize.Companion.Saver(): Saver<IntSize, *> = Saver(
|
|||||||
restore = { IntSize(it.first, it.second) }
|
restore = { IntSize(it.first, it.second) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private var lastExecutedComposables = HashSet<Any>()
|
||||||
|
private val failedComposables = HashSet<Any>()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun tryOrShowError(key: Any = Exception().stackTraceToString().lines()[2], error: @Composable () -> Unit = {}, content: @Composable () -> Unit) {
|
||||||
|
if (!failedComposables.contains(key)) {
|
||||||
|
lastExecutedComposables.add(key)
|
||||||
|
content()
|
||||||
|
lastExecutedComposables.remove(key)
|
||||||
|
} else {
|
||||||
|
error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun includeMoreFailedComposables() {
|
||||||
|
lastExecutedComposables.forEach {
|
||||||
|
failedComposables.add(it)
|
||||||
|
Log.i(TAG, "Added composable key as failed: $it")
|
||||||
|
}
|
||||||
|
lastExecutedComposables.clear()
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) {
|
fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) {
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
<string name="moderated_description">moderated</string>
|
<string name="moderated_description">moderated</string>
|
||||||
<string name="invalid_chat">invalid chat</string>
|
<string name="invalid_chat">invalid chat</string>
|
||||||
<string name="invalid_data">invalid data</string>
|
<string name="invalid_data">invalid data</string>
|
||||||
|
<string name="error_showing_message">error showing message</string>
|
||||||
|
<string name="error_showing_content">error showing content</string>
|
||||||
|
|
||||||
<string name="decryption_error">Decryption error</string>
|
<string name="decryption_error">Decryption error</string>
|
||||||
<string name="encryption_renegotiation_error">Encryption re-negotiation error</string>
|
<string name="encryption_renegotiation_error">Encryption re-negotiation error</string>
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ fun showApp() {
|
|||||||
Log.e(TAG, "App crashed, thread name: " + Thread.currentThread().name + ", exception: " + e.stackTraceToString())
|
Log.e(TAG, "App crashed, thread name: " + Thread.currentThread().name + ", exception: " + e.stackTraceToString())
|
||||||
window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
|
window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSING))
|
||||||
closedByError.value = true
|
closedByError.value = true
|
||||||
|
includeMoreFailedComposables()
|
||||||
// If the left side of screen has open modal, it's probably caused the crash
|
// If the left side of screen has open modal, it's probably caused the crash
|
||||||
if (ModalManager.start.hasModalsOpen()) {
|
if (ModalManager.start.hasModalsOpen()) {
|
||||||
ModalManager.start.closeModal()
|
ModalManager.start.closeModal()
|
||||||
|
Loading…
Reference in New Issue
Block a user