From 29b27fa602494a6257b73a2644d2904027a9610f Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 14 Sep 2022 23:27:17 +0300 Subject: [PATCH] android: progress indicator in database related views (#1052) Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- .../views/database/DatabaseEncryptionView.kt | 34 ++++++++++++------- .../app/views/database/DatabaseErrorView.kt | 34 ++++++++++++++++--- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt index 40726a4e55..3298ead4ac 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt @@ -58,6 +58,7 @@ fun DatabaseEncryptionView(m: ChatModel) { confirmNewKey, storedKey, initialRandomDBPassphrase, + progressIndicator, onConfirmEncrypt = { progressIndicator.value = true withApi { @@ -127,6 +128,7 @@ fun DatabaseEncryptionLayout( confirmNewKey: MutableState, storedKey: MutableState, initialRandomDBPassphrase: MutableState, + progressIndicator: MutableState, onConfirmEncrypt: () -> Unit, ) { Column( @@ -140,7 +142,7 @@ fun DatabaseEncryptionLayout( ) SectionView(null) { - SavePassphraseSetting(useKeychain.value, initialRandomDBPassphrase.value, storedKey.value) { checked -> + SavePassphraseSetting(useKeychain.value, initialRandomDBPassphrase.value, storedKey.value, progressIndicator.value) { checked -> if (checked) { setUseKeychain(true, useKeychain, prefs) } else if (storedKey.value) { @@ -179,23 +181,27 @@ fun DatabaseEncryptionLayout( keyboardActions = KeyboardActions(onNext = { defaultKeyboardAction(ImeAction.Next) }), ) val onClickUpdate = { - if (currentKey.value == "") { - if (useKeychain.value) - encryptDatabaseSavedAlert(onConfirmEncrypt) - else - encryptDatabaseAlert(onConfirmEncrypt) - } else { - if (useKeychain.value) - changeDatabaseKeySavedAlert(onConfirmEncrypt) - else - changeDatabaseKeyAlert(onConfirmEncrypt) + // Don't do things concurrently. Shouldn't be here concurrently, just in case + if (!progressIndicator.value) { + if (currentKey.value == "") { + if (useKeychain.value) + encryptDatabaseSavedAlert(onConfirmEncrypt) + else + encryptDatabaseAlert(onConfirmEncrypt) + } else { + if (useKeychain.value) + changeDatabaseKeySavedAlert(onConfirmEncrypt) + else + changeDatabaseKeyAlert(onConfirmEncrypt) + } } } val disabled = currentKey.value == newKey.value || newKey.value != confirmNewKey.value || newKey.value.isEmpty() || !validKey(currentKey.value) || - !validKey(newKey.value) + !validKey(newKey.value) || + progressIndicator.value DatabaseKeyField( confirmNewKey, @@ -280,6 +286,7 @@ fun SavePassphraseSetting( useKeychain: Boolean, initialRandomDBPassphrase: Boolean, storedKey: Boolean, + progressIndicator: Boolean, onCheckedChange: (Boolean) -> Unit, ) { SectionItemView() { @@ -303,7 +310,7 @@ fun SavePassphraseSetting( checkedThumbColor = MaterialTheme.colors.primary, uncheckedThumbColor = HighOrLowlight ), - enabled = !initialRandomDBPassphrase + enabled = !initialRandomDBPassphrase && !progressIndicator ) } } @@ -495,6 +502,7 @@ fun PreviewDatabaseEncryptionLayout() { confirmNewKey = remember { mutableStateOf("") }, storedKey = remember { mutableStateOf(true) }, initialRandomDBPassphrase = remember { mutableStateOf(true) }, + progressIndicator = remember { mutableStateOf(false) }, onConfirmEncrypt = {}, ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt index 13becac525..82454bf901 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt @@ -26,6 +26,7 @@ fun DatabaseErrorView( chatDbStatus: State, appPreferences: AppPreferences, ) { + val progressIndicator = remember { mutableStateOf(false) } val dbKey = remember { mutableStateOf("") } var storedDBKey by remember { mutableStateOf(DatabaseUtils.getDatabaseKey()) } var useKeychain by remember { mutableStateOf(appPreferences.storeDBPassphrase.get()) } @@ -35,7 +36,7 @@ fun DatabaseErrorView( appPreferences.storeDBPassphrase.set(true) useKeychain = true appPreferences.initialRandomDBPassphrase.set(false) - runChat(dbKey.value, chatDbStatus, appPreferences) + runChat(dbKey.value, chatDbStatus, progressIndicator, appPreferences) } val title = when (chatDbStatus.value) { is DBMigrationResult.OK -> "" @@ -63,7 +64,7 @@ fun DatabaseErrorView( Column( Modifier.padding(horizontal = 8.dp, vertical = 8.dp) ) { - val buttonEnabled = validKey(dbKey.value) + val buttonEnabled = validKey(dbKey.value) && !progressIndicator.value when (val status = chatDbStatus.value) { is DBMigrationResult.ErrorNotADatabase -> { if (useKeychain && !storedDBKey.isNullOrEmpty()) { @@ -77,12 +78,12 @@ fun DatabaseErrorView( } else { Text(generalGetString(R.string.database_passphrase_is_required)) DatabaseKeyField(dbKey, buttonEnabled) { - if (useKeychain) saveAndRunChatOnClick() else runChat(dbKey.value, chatDbStatus, appPreferences) + if (useKeychain) saveAndRunChatOnClick() else runChat(dbKey.value, chatDbStatus, progressIndicator, appPreferences) } if (useKeychain) { SaveAndOpenButton(buttonEnabled, saveAndRunChatOnClick) } else { - OpenChatButton(buttonEnabled) { runChat(dbKey.value, chatDbStatus, appPreferences) } + OpenChatButton(buttonEnabled) { runChat(dbKey.value, chatDbStatus, progressIndicator, appPreferences) } } } } @@ -104,14 +105,37 @@ fun DatabaseErrorView( } } } + if (progressIndicator.value) { + Box( + Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + Modifier + .padding(horizontal = 2.dp) + .size(30.dp), + color = HighOrLowlight, + strokeWidth = 2.5.dp + ) + } + } } -private fun runChat(dbKey: String, chatDbStatus: State, prefs: AppPreferences) { +private fun runChat( + dbKey: String, + chatDbStatus: State, + progressIndicator: MutableState, + prefs: AppPreferences +) = CoroutineScope(Dispatchers.Default).launch { + // Don't do things concurrently. Shouldn't be here concurrently, just in case + if (progressIndicator.value) return@launch + progressIndicator.value = true try { SimplexApp.context.initChatController(dbKey) } catch (e: Exception) { Log.d(TAG, "initializeChat ${e.stackTraceToString()}") } + progressIndicator.value = false when (val status = chatDbStatus.value) { is DBMigrationResult.OK -> { SimplexService.cancelPassphraseNotification()