diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt index bfa1770d9..dd760e0b1 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexService.kt @@ -104,7 +104,7 @@ class SimplexService: Service() { if (wakeLock != null || isStartingService) return val self = this isStartingService = true - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val chatController = ChatController waitDbMigrationEnds(chatController) try { @@ -114,7 +114,7 @@ class SimplexService: Service() { Log.w(chat.simplex.app.TAG, "SimplexService: problem with the database: $chatDbStatus") showPassphraseNotification(chatDbStatus) safeStopService() - return@withBGApi + return@withLongRunningApi } saveServiceState(self, ServiceState.STARTED) wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run { diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt index 25369ffdf..ff83c10df 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/helpers/SoundPlayer.kt @@ -8,9 +8,7 @@ import androidx.core.content.ContextCompat import chat.simplex.common.R import chat.simplex.common.platform.SoundPlayerInterface import chat.simplex.common.platform.androidAppContext -import chat.simplex.common.views.helpers.withScope -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay +import kotlinx.coroutines.* object SoundPlayer: SoundPlayerInterface { private var player: MediaPlayer? = null @@ -31,7 +29,7 @@ object SoundPlayer: SoundPlayerInterface { val vibrator = ContextCompat.getSystemService(androidAppContext, Vibrator::class.java) val effect = VibrationEffect.createOneShot(250, VibrationEffect.DEFAULT_AMPLITUDE) playing = true - withScope(scope) { + scope.launch { while (playing) { if (sound) player?.start() vibrator?.vibrate(effect) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt index 5f30d21bb..ac14b5199 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt @@ -383,7 +383,7 @@ private fun DisabledBackgroundCallsButton() { Modifier .padding(bottom = 24.dp) .clickable { - withBGApi { + withLongRunningApi { show = !platform.androidAskToAllowBackgroundCalls() } } diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt index 362d793e8..b8f5abc50 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/newchat/QRCodeScanner.android.kt @@ -133,7 +133,7 @@ actual fun QRCodeScanner( } } !cameraPermissionState.hasPermission -> { - Button({ withBGApi { cameraPermissionState.launchPermissionRequest() } }, modifier = modifier, colors = buttonColors) { + Button({ cameraPermissionState.launchPermissionRequest() }, modifier = modifier, colors = buttonColors) { Icon(painterResource(MR.images.ic_camera_enhance), null) Spacer(Modifier.width(DEFAULT_PADDING_HALF)) Text(stringResource(MR.strings.enable_camera_access)) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt index 932d259df..e02c011fa 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt @@ -102,7 +102,7 @@ fun AppearanceScope.AppearanceLayout( val state = rememberSaveable { mutableStateOf(languagePref.get() ?: "system") } LangSelector(state) { state.value = it - withBGApi { + withApi { delay(200) val activity = context as? Activity if (activity != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt index c9ede4848..a75ee7590 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/platform/NtfManager.kt @@ -55,7 +55,7 @@ abstract class NtfManager { } fun openChatAction(userId: Long?, chatId: ChatId) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { awaitChatStartedIfNeeded(chatModel) if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) { // TODO include remote host ID in desktop notifications? @@ -70,7 +70,7 @@ abstract class NtfManager { } fun showChatsAction(userId: Long?) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { awaitChatStartedIfNeeded(chatModel) if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) { // TODO include remote host ID in desktop notifications? diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt index cd0c424e0..e5982d01d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeView.kt @@ -267,7 +267,7 @@ fun ComposeView( fun loadLinkPreview(url: String, wait: Long? = null) { if (pendingLinkUrl.value == url) { composeState.value = composeState.value.copy(preview = ComposePreview.CLinkPreview(null)) - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { if (wait != null) delay(wait) val lp = getLinkPreview(url) if (lp != null && pendingLinkUrl.value == url) { @@ -551,7 +551,7 @@ fun ComposeView( } fun sendMessage(ttl: Int?) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { sendMessageAsync(null, false, ttl) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt index 56656b7fc..e4f31748c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt @@ -54,7 +54,7 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea }, inviteMembers = { allowModifyMembers = false - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { for (contactId in selectedContacts) { val member = chatModel.controller.apiAddMember(rhId, groupInfo.groupId, contactId, selectedRole.value) if (member != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt index 24e9fd691..6a1db9249 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIFileView.kt @@ -94,7 +94,7 @@ fun CIFileView( FileProtocol.LOCAL -> {} } file.fileStatus is CIFileStatus.RcvComplete || (file.fileStatus is CIFileStatus.SndStored && file.fileProtocol == FileProtocol.LOCAL) -> { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { var filePath = getLoadedFilePath(file) if (chatModel.connectedToRemote() && filePath == null) { file.loadRemoteFile(true) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt index 413d95b67..a5a952108 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/CIVIdeoView.kt @@ -41,7 +41,7 @@ fun CIVideoView( val filePath = remember(file, CIFile.cachedRemoteFileRequests.toList()) { mutableStateOf(getLoadedFilePath(file)) } if (chatModel.connectedToRemote()) { LaunchedEffect(file) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { if (file != null && file.loaded && getLoadedFilePath(file) == null) { file.loadRemoteFile(false) filePath.value = getLoadedFilePath(file) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index 073d10887..8f49ce92c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -213,7 +213,7 @@ fun ChatItemView( showMenu.value = false } if (chatModel.connectedToRemote() && fileSource == null) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { cItem.file?.loadRemoteFile(true) fileSource = getLoadedFileSource(cItem.file) shareIfExists() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt index 406f79d45..86558162d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt @@ -62,7 +62,7 @@ fun DatabaseEncryptionView(m: ChatModel) { initialRandomDBPassphrase, progressIndicator, onConfirmEncrypt = { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { encryptDatabase(currentKey, newKey, confirmNewKey, initialRandomDBPassphrase, useKeychain, storedKey, progressIndicator) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index 58d3bfd63..2d644b297 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -368,7 +368,7 @@ fun chatArchiveTitle(chatArchiveTime: Instant, chatLastStart: Instant): String { } fun startChat(m: ChatModel, chatLastStart: MutableState, chatDbChanged: MutableState, progressIndicator: MutableState? = null) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { try { progressIndicator?.value = true if (chatDbChanged.value) { @@ -378,12 +378,12 @@ fun startChat(m: ChatModel, chatLastStart: MutableState, chatDbChanged if (m.chatDbStatus.value !is DBMigrationResult.OK) { /** Hide current view and show [DatabaseErrorView] */ ModalManager.closeAllModalsEverywhere() - return@withBGApi + return@withLongRunningApi } val user = m.currentUser.value if (user == null) { ModalManager.closeAllModalsEverywhere() - return@withBGApi + return@withLongRunningApi } else { m.controller.startChat(user) } @@ -581,7 +581,7 @@ private fun importArchive( progressIndicator.value = true val archivePath = saveArchiveFromURI(importedArchiveURI) if (archivePath != null) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 180_000) { try { m.controller.apiDeleteStorage() try { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt index d98f38d71..b645cb1ee 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ProcessedErrors.kt @@ -16,7 +16,7 @@ class ProcessedErrors (val interval: Long) { fun newError(error: T, offerRestart: Boolean) { timer.cancel() - timer = withBGApi { + timer = withLongRunningApi(slow = 70_000, deadlock = 130_000) { val delayBeforeNext = (lastShownTimestamp + interval) - System.currentTimeMillis() if ((lastShownOfferRestart || !offerRestart) && delayBeforeNext >= 0) { delay(delayBeforeNext) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index 75c730b72..33ee72841 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -27,11 +27,9 @@ import kotlin.math.* private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() -fun withApi(action: suspend CoroutineScope.() -> Unit): Job = withScope(GlobalScope, action) - -fun withScope(scope: CoroutineScope, action: suspend CoroutineScope.() -> Unit): Job = +fun withApi(action: suspend CoroutineScope.() -> Unit): Job = Exception().let { - scope.launch { withContext(Dispatchers.Main, block = { wrapWithLogging(action, it) }) } + CoroutineScope(Dispatchers.Main).launch(block = { wrapWithLogging(action, it) }) } fun withBGApi(action: suspend CoroutineScope.() -> Unit): Job = diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt index cf10d33cb..1048b03bc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/localauth/LocalAuthView.kt @@ -49,7 +49,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) { } private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (LAResult) -> Unit) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { try { /** Waiting until [initChatController] finishes */ while (m.ctrlInitInProgress.value) { @@ -78,7 +78,7 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: ( displayNamePref.set(null) reinitChatController() if (m.currentUser.value != null) { - return@withBGApi + return@withLongRunningApi } var profile: Profile? = null if (!displayName.isNullOrEmpty()) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt index 9dd3e20c2..854770489 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/SetupDatabasePassphrase.kt @@ -50,7 +50,7 @@ fun SetupDatabasePassphrase(m: ChatModel) { confirmNewKey, progressIndicator, onConfirmEncrypt = { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { if (m.chatRunning.value == true) { // Stop chat if it's started before doing anything stopChatAsync(m) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt index e6ec2ba23..76aa905b8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt @@ -96,7 +96,7 @@ fun PrivacySettingsView( val currentUser = chatModel.currentUser.value if (currentUser != null) { fun setSendReceiptsContacts(enable: Boolean, clearOverrides: Boolean) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val mrs = UserMsgReceiptSettings(enable, clearOverrides) chatModel.controller.apiSetUserContactReceipts(currentUser, mrs) chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true) @@ -119,7 +119,7 @@ fun PrivacySettingsView( } fun setSendReceiptsGroups(enable: Boolean, clearOverrides: Boolean) { - withBGApi { + withLongRunningApi(slow = 30_000, deadlock = 60_000) { val mrs = UserMsgReceiptSettings(enable, clearOverrides) chatModel.controller.apiSetUserGroupReceipts(currentUser, mrs) chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt index b6d18aaf8..50d143aaf 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/RecAndPlay.desktop.kt @@ -211,15 +211,13 @@ actual object SoundPlayer: SoundPlayerInterface { var playing = false override fun start(scope: CoroutineScope, sound: Boolean) { - withBGApi { - val tmpFile = File(tmpDir, UUID.randomUUID().toString()) - tmpFile.deleteOnExit() - SoundPlayer::class.java.getResource("/media/ring_once.mp3").openStream()!!.use { it.copyTo(tmpFile.outputStream()) } - playing = true - while (playing) { - if (sound) { - AudioPlayer.play(CryptoFile.plain(tmpFile.absolutePath), mutableStateOf(true), mutableStateOf(0), mutableStateOf(0), true) - } + val tmpFile = File(tmpDir, UUID.randomUUID().toString()) + tmpFile.deleteOnExit() + SoundPlayer::class.java.getResource("/media/ring_once.mp3").openStream()!!.use { it.copyTo(tmpFile.outputStream()) } + playing = true + scope.launch { + while (playing && sound) { + AudioPlayer.play(CryptoFile.plain(tmpFile.absolutePath), mutableStateOf(true), mutableStateOf(0), mutableStateOf(0), true) delay(3500) } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt index b5e0968c8..29e9d5bae 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.desktop.kt @@ -42,7 +42,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL } var fileSource = getLoadedFileSource(cItem.file) if (chatModel.connectedToRemote() && fileSource == null) { - withBGApi { + withLongRunningApi(slow = 60_000, deadlock = 600_000) { cItem.file?.loadRemoteFile(true) fileSource = getLoadedFileSource(cItem.file) saveIfExists() @@ -51,7 +51,7 @@ actual fun SaveContentItemAction(cItem: ChatItem, saveFileLauncher: FileChooserL }) } -actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withBGApi { +actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = withLongRunningApi(slow = 60_000, deadlock = 600_000) { var fileSource = getLoadedFileSource(cItem.file) if (chatModel.connectedToRemote() && fileSource == null) { cItem.file?.loadRemoteFile(true) @@ -63,10 +63,10 @@ actual fun copyItemToClipboard(cItem: ChatItem, clipboard: ClipboardManager) = w val tmpFile = File(tmpDir, fileSource.filePath) tmpFile.deleteOnExit() try { - decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs ?: return@withBGApi, tmpFile.absolutePath) + decryptCryptoFile(getAppFilePath(fileSource.filePath), fileSource.cryptoArgs ?: return@withLongRunningApi, tmpFile.absolutePath) } catch (e: Exception) { Log.e(TAG, "Unable to decrypt crypto file: " + e.stackTraceToString()) - return@withBGApi + return@withLongRunningApi } tmpFile.absolutePath } else { diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt index 8d7cbed84..1a8ad010e 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt @@ -51,7 +51,7 @@ fun AppearanceScope.AppearanceLayout( val state = rememberSaveable { mutableStateOf(languagePref.get() ?: "system") } LangSelector(state) { state.value = it - withBGApi { + withApi { delay(200) if (it == "system") { languagePref.set(null)