From 9cf3a37a2b25fa127cc0c0c904c9849a3bf45e79 Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Tue, 2 Jul 2024 09:25:19 +0930 Subject: [PATCH] Handle backpresses in onboarding --- .../securesms/ApplicationContext.java | 14 +--- .../securesms/onboarding/landing/Landing.kt | 8 +- .../onboarding/landing/LandingActivity.kt | 5 +- .../loadaccount/LoadAccountActivity.kt | 5 +- .../onboarding/loading/LoadingActivity.kt | 9 +-- .../{loading => manager}/LoadingManager.kt | 2 +- .../MessageNotifications.kt | 52 ++++++++++-- .../MessageNotificationsActivity.kt | 41 ++++++++-- .../MessageNotificationsViewModel.kt | 81 ++++++++++++++++--- .../pickname/PickDisplayNameActivity.kt | 10 +-- .../pickname/PickDisplayNameViewModel.kt | 12 ++- .../preferences/ClearAllDataDialog.kt | 4 +- .../securesms/preferences/SettingsActivity.kt | 13 +-- .../thoughtcrime/securesms/ui/AlertDialog.kt | 17 ++-- .../thoughtcrime/securesms/ui/Components.kt | 8 +- .../components/CircularProgressIndicator.kt | 26 ++++++ app/src/main/res/values/strings.xml | 3 + 17 files changed, 230 insertions(+), 80 deletions(-) rename app/src/main/java/org/thoughtcrime/securesms/onboarding/{loading => manager}/LoadingManager.kt (97%) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/ui/components/CircularProgressIndicator.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 2e21dacd54..ae9d243adc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -18,6 +18,7 @@ package org.thoughtcrime.securesms; import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant; import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant; +import android.annotation.SuppressLint; import android.app.Application; import android.content.Context; import android.content.Intent; @@ -137,7 +138,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO public MessageNotifier messageNotifier = null; public Poller poller = null; public Broadcaster broadcaster = null; - private Job firebaseInstanceIdJob; private WindowDebouncer conversationListDebouncer; private HandlerThread conversationListHandlerThread; private Handler conversationListHandler; @@ -504,17 +504,9 @@ public class ApplicationContext extends Application implements DefaultLifecycleO }); } - public void clearAllData(boolean isMigratingToV2KeyPair) { - if (firebaseInstanceIdJob != null && firebaseInstanceIdJob.isActive()) { - firebaseInstanceIdJob.cancel(null); - } - String displayName = TextSecurePreferences.getProfileName(this); - boolean isUsingFCM = TextSecurePreferences.isPushEnabled(this); + @SuppressLint("ApplySharedPref") + public void clearAllData() { TextSecurePreferences.clearAll(this); - if (isMigratingToV2KeyPair) { - TextSecurePreferences.setPushEnabled(this, isUsingFCM); - TextSecurePreferences.setProfileName(this, displayName); - } getSharedPreferences(PREFERENCES_NAME, 0).edit().clear().commit(); if (!deleteDatabase(SQLCipherOpenHelper.DATABASE_NAME)) { Log.d("Loki", "Failed to delete database."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/Landing.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/Landing.kt index 78e9c8913d..55d0cb14e2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/Landing.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/Landing.kt @@ -82,13 +82,13 @@ internal fun LandingScreen( text = stringResource(R.string.urlOpenBrowser), buttons = listOf( DialogButtonModel( - GetString(R.string.activity_landing_terms_of_service), - GetString(R.string.AccessibilityId_terms_of_service_button), + text = GetString(R.string.activity_landing_terms_of_service), + contentDescription = GetString(R.string.AccessibilityId_terms_of_service_button), onClick = openTerms ), DialogButtonModel( - GetString(R.string.activity_landing_privacy_policy), - GetString(R.string.AccessibilityId_privacy_policy_button), + text = GetString(R.string.activity_landing_privacy_policy), + contentDescription = GetString(R.string.AccessibilityId_privacy_policy_button), onClick = openPrivacyPolicy ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt index 1b7fce5326..3be3eafcc2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt @@ -32,10 +32,7 @@ class LandingActivity: BaseActionBarActivity() { setComposeContent { LandingScreen( - createAccount = { - prefs.setHasViewedSeed(false) - startPickDisplayNameActivity() - }, + createAccount = { startPickDisplayNameActivity() }, loadAccount = { start() }, openTerms = { open("https://getsession.org/terms-of-service") }, openPrivacyPolicy = { open("https://getsession.org/privacy-policy") } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt index 55df7f9c02..e45c782b56 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt @@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.onboarding.loadaccount import android.os.Bundle import androidx.activity.viewModels -import androidx.camera.core.ExperimentalGetImage import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.lifecycle.lifecycleScope @@ -11,14 +10,13 @@ import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.BaseActionBarActivity -import org.thoughtcrime.securesms.onboarding.loading.LoadingManager +import org.thoughtcrime.securesms.onboarding.manager.LoadingManager import org.thoughtcrime.securesms.onboarding.messagenotifications.MessageNotificationsActivity import org.thoughtcrime.securesms.ui.setComposeContent import org.thoughtcrime.securesms.util.start import javax.inject.Inject @AndroidEntryPoint -@androidx.annotation.OptIn(ExperimentalGetImage::class) class LoadAccountActivity : BaseActionBarActivity() { @Inject @@ -31,7 +29,6 @@ class LoadAccountActivity : BaseActionBarActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) supportActionBar?.setTitle(R.string.activity_link_load_account) - prefs.setHasViewedSeed(true) prefs.setConfigurationMessageSynced(false) prefs.setRestorationTime(System.currentTimeMillis()) prefs.setLastProfileUpdateTime(0) diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt index 37a63ad1d6..0b76dd829d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt @@ -28,11 +28,6 @@ class LoadingActivity: BaseActionBarActivity() { private val viewModel: LoadingViewModel by viewModels() - @Deprecated("Deprecated in Java") - override fun onBackPressed() { - return - } - private fun register(loadFailed: Boolean) { prefs.setLastConfigurationSyncTime(System.currentTimeMillis()) @@ -47,6 +42,8 @@ class LoadingActivity: BaseActionBarActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setUpActionBarSessionLogo() + ApplicationContext.getInstance(this).newAccount = false setComposeContent { @@ -54,8 +51,6 @@ class LoadingActivity: BaseActionBarActivity() { LoadingScreen(state) } - setUpActionBarSessionLogo(true) - lifecycleScope.launch { viewModel.events.collect { when (it) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingManager.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadingManager.kt similarity index 97% rename from app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingManager.kt rename to app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadingManager.kt index ed312fbb89..c805839740 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadingManager.kt @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.onboarding.loading +package org.thoughtcrime.securesms.onboarding.manager import android.content.Context import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotifications.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotifications.kt index d68fd38051..1b0be5506c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotifications.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotifications.kt @@ -31,7 +31,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import network.loki.messenger.R +import org.thoughtcrime.securesms.onboarding.messagenotifications.MessageNotificationsViewModel.UiState import org.thoughtcrime.securesms.onboarding.ui.ContinuePrimaryOutlineButton +import org.thoughtcrime.securesms.ui.AlertDialog +import org.thoughtcrime.securesms.ui.DialogButtonModel +import org.thoughtcrime.securesms.ui.GetString import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.SessionColorsParameterProvider @@ -39,6 +43,7 @@ import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.color.Colors import org.thoughtcrime.securesms.ui.color.LocalColors import org.thoughtcrime.securesms.ui.color.transparentButtonColors +import org.thoughtcrime.securesms.ui.components.CircularProgressIndicator import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h4 import org.thoughtcrime.securesms.ui.h8 @@ -47,10 +52,39 @@ import org.thoughtcrime.securesms.ui.small @Composable internal fun MessageNotificationsScreen( - state: MessageNotificationsState = MessageNotificationsState(), + state: UiState = UiState(), setEnabled: (Boolean) -> Unit = {}, - onContinue: () -> Unit = {} + onContinue: () -> Unit = {}, + quit: () -> Unit = {}, + dismissDialog: () -> Unit = {} ) { + if (state.clearData) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator(LocalColors.current.primary) + } + + return + } + + if (state.showDialog) AlertDialog( + onDismissRequest = dismissDialog, + title = stringResource(R.string.warning), + text = stringResource(R.string.you_cannot_go_back_further_in_order_to_stop_loading_your_account_session_needs_to_quit), + buttons = listOf( + DialogButtonModel( + GetString(stringResource(R.string.quit)), + color = LocalColors.current.danger, + onClick = quit + ), + DialogButtonModel( + GetString(stringResource(R.string.cancel)) + ) + ) + ) + Column { Spacer(Modifier.weight(1f)) @@ -105,9 +139,15 @@ private fun NotificationRadioButton( Box( modifier = Modifier .weight(1f) - .border(LocalDimensions.current.borderStroke, LocalColors.current.borders, RoundedCornerShape(8.dp)), + .border( + LocalDimensions.current.borderStroke, + LocalColors.current.borders, + RoundedCornerShape(8.dp) + ), ) { - Column(modifier = Modifier.padding(horizontal = 15.dp).padding(top = 10.dp, bottom = 11.dp)) { + Column(modifier = Modifier + .padding(horizontal = 15.dp) + .padding(top = 10.dp, bottom = 11.dp)) { Text(stringResource(title), style = h8) Text(stringResource(explanation), style = small, modifier = Modifier.padding(top = 7.dp)) @@ -139,7 +179,9 @@ private fun RadioButtonIndicator( Box(modifier = modifier) { AnimatedVisibility( selected, - modifier = Modifier.padding(2.5.dp).clip(CircleShape), + modifier = Modifier + .padding(2.5.dp) + .clip(CircleShape), enter = scaleIn(), exit = scaleOut() ) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt index 12a19ed783..887345c44b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.onboarding.messagenotifications +import android.app.Activity import android.os.Bundle import androidx.activity.viewModels import androidx.compose.runtime.Composable @@ -12,7 +13,8 @@ import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.home.startHomeActivity import org.thoughtcrime.securesms.notifications.PushRegistry import org.thoughtcrime.securesms.onboarding.loading.LoadingActivity -import org.thoughtcrime.securesms.onboarding.loading.LoadingManager +import org.thoughtcrime.securesms.onboarding.manager.LoadingManager +import org.thoughtcrime.securesms.onboarding.messagenotifications.MessageNotificationsActivity.Companion.EXTRA_PROFILE_NAME import org.thoughtcrime.securesms.ui.setComposeContent import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo import org.thoughtcrime.securesms.util.start @@ -21,11 +23,22 @@ import javax.inject.Inject @AndroidEntryPoint class MessageNotificationsActivity : BaseActionBarActivity() { + companion object { + const val EXTRA_PROFILE_NAME = "EXTRA_PROFILE_NAME" + } + + @Inject + internal lateinit var viewModelFactory: MessageNotificationsViewModel.AssistedFactory + @Inject lateinit var pushRegistry: PushRegistry @Inject lateinit var prefs: TextSecurePreferences @Inject lateinit var loadingManager: LoadingManager - private val viewModel: MessageNotificationsViewModel by viewModels() + val profileName by lazy { intent.getStringExtra(EXTRA_PROFILE_NAME) } + + private val viewModel: MessageNotificationsViewModel by viewModels { + viewModelFactory.create(profileName) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -35,14 +48,28 @@ class MessageNotificationsActivity : BaseActionBarActivity() { setComposeContent { MessageNotificationsScreen() } } + @Deprecated("Deprecated in Java") + override fun onBackPressed() { + if (viewModel.onBackPressed()) return + + @Suppress("DEPRECATION") + super.onBackPressed() + } + @Composable private fun MessageNotificationsScreen() { - val state by viewModel.states.collectAsState() - MessageNotificationsScreen(state, viewModel::setEnabled, ::register) + val uiState by viewModel.uiStates.collectAsState() + MessageNotificationsScreen( + uiState, + setEnabled = viewModel::setEnabled, + onContinue = ::register, + quit = viewModel::quit, + dismissDialog = viewModel::dismissDialog + ) } private fun register() { - prefs.setPushEnabled(viewModel.states.value.pushEnabled) + prefs.setPushEnabled(viewModel.uiStates.value.pushEnabled) ApplicationContext.getInstance(this).startPollingIfNeeded() pushRegistry.refresh(true) @@ -52,3 +79,7 @@ class MessageNotificationsActivity : BaseActionBarActivity() { } } } + +fun Activity.startMessageNotificationsActivity(profileName: String) { + start { putExtra(EXTRA_PROFILE_NAME, profileName) } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt index 8312d16786..003eef5255 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt @@ -1,22 +1,83 @@ package org.thoughtcrime.securesms.onboarding.messagenotifications +import android.app.Application +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel -import dagger.hilt.android.lifecycle.HiltViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -import javax.inject.Inject +import kotlinx.coroutines.launch +import org.thoughtcrime.securesms.ApplicationContext -@HiltViewModel -internal class MessageNotificationsViewModel @Inject constructor(): ViewModel() { - private val _states = MutableStateFlow(MessageNotificationsState()) - val states = _states.asStateFlow() +internal class MessageNotificationsViewModel( + private val state: State, + private val application: Application +): AndroidViewModel(application) { + private val _uiStates = MutableStateFlow(UiState()) + val uiStates = _uiStates.asStateFlow() fun setEnabled(enabled: Boolean) { - _states.update { MessageNotificationsState(pushEnabled = enabled) } + _uiStates.update { UiState(pushEnabled = enabled) } + } + + /** + * @return [true] if the back press was handled. + */ + fun onBackPressed(): Boolean = when (state) { + is State.CreateAccount -> false + is State.LoadAccount -> { + _uiStates.update { it.copy(showDialog = true) } + + true + } + } + + fun dismissDialog() { + _uiStates.update { it.copy(showDialog = false) } + } + + fun quit() { + _uiStates.update { it.copy(clearData = true) } + + viewModelScope.launch(Dispatchers.IO) { + ApplicationContext.getInstance(application).clearAllData() + } } -} -data class MessageNotificationsState(val pushEnabled: Boolean = true) { - val pushDisabled get() = !pushEnabled + data class UiState( + val pushEnabled: Boolean = true, + val showDialog: Boolean = false, + val clearData: Boolean = false + ) { + val pushDisabled get() = !pushEnabled + } + + sealed interface State { + class CreateAccount(val displayName: String): State + object LoadAccount: State + } + + @dagger.assisted.AssistedFactory + interface AssistedFactory { + fun create(profileName: String?): Factory + } + + @Suppress("UNCHECKED_CAST") + class Factory @AssistedInject constructor( + @Assisted private val profileName: String?, + private val application: Application + ) : ViewModelProvider.Factory { + + override fun create(modelClass: Class): T { + return MessageNotificationsViewModel( + state = profileName?.let(State::CreateAccount) ?: State.LoadAccount, + application = application + ) as T + } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt index a0c2e01fb6..a0ac2ac08d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt @@ -13,10 +13,9 @@ import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.home.startHomeActivity -import org.thoughtcrime.securesms.onboarding.messagenotifications.MessageNotificationsActivity +import org.thoughtcrime.securesms.onboarding.messagenotifications.startMessageNotificationsActivity import org.thoughtcrime.securesms.ui.setComposeContent import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo -import org.thoughtcrime.securesms.util.start import javax.inject.Inject private const val EXTRA_LOAD_FAILED = "extra_load_failed" @@ -41,11 +40,12 @@ class PickDisplayNameActivity : BaseActionBarActivity() { setComposeContent { DisplayNameScreen(viewModel) } - if (!loadFailed) prefs.setHasViewedSeed(false) - lifecycleScope.launch { viewModel.events.collect { - if (loadFailed) startHomeActivity() else start() + when (it) { + is Event.CreateAccount -> startMessageNotificationsActivity(it.profileName) + Event.LoadAccountComplete -> startHomeActivity() + } } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameViewModel.kt index 2dca93064b..51f82a677e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameViewModel.kt @@ -49,6 +49,7 @@ internal class PickDisplayNameViewModel( _states.update { it.copy(isTextErrorColor = false, error = null) } prefs.setProfileName(displayName) + configFactory.user?.setName(displayName) if (!loadFailed) { // This is here to resolve a case where the app restarts before a user completes onboarding @@ -70,7 +71,13 @@ internal class PickDisplayNameViewModel( prefs.setRestorationTime(0) } - viewModelScope.launch { _events.emit(Event.DONE) } + viewModelScope.launch { + if (loadFailed) { + _events.emit(Event.LoadAccountComplete) + } else { + _events.emit(Event.CreateAccount(displayName)) + } + } } } } @@ -116,5 +123,6 @@ fun pickNewNameState() = State( ) sealed interface Event { - object DONE: Event + class CreateAccount(val profileName: String): Event + object LoadAccountComplete: Event } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt index 31f2782f8f..008efbfe42 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt @@ -110,7 +110,7 @@ class ClearAllDataDialog : DialogFragment() { } catch (e: Exception) { Log.e("Loki", "Failed to force sync", e) } - ApplicationContext.getInstance(context).clearAllData(false) + ApplicationContext.getInstance(context).clearAllData() withContext(Dispatchers.Main) { dismiss() } @@ -133,7 +133,7 @@ class ClearAllDataDialog : DialogFragment() { } } else if (result.values.all { it }) { // don't force sync because all the messages are deleted? - ApplicationContext.getInstance(context).clearAllData(false) + ApplicationContext.getInstance(context).clearAllData() withContext(Dispatchers.Main) { dismiss() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index ebd79a716e..0ef4b800fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -18,6 +18,7 @@ import android.view.View import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -25,14 +26,9 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.core.view.isInvisible import androidx.core.view.isVisible @@ -44,11 +40,8 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.startWith import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import network.loki.messenger.BuildConfig import network.loki.messenger.R import network.loki.messenger.databinding.ActivitySettingsBinding @@ -420,7 +413,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { Cell { Column { - LargeItemButtonWithDrawable(R.string.activity_path_title, if (hasPaths) R.drawable.ic_status else R.drawable.ic_path_yellow) { show() } + Crossfade(if (hasPaths) R.drawable.ic_status else R.drawable.ic_path_yellow, label = "path") { + LargeItemButtonWithDrawable(R.string.activity_path_title, it) { show() } + } Divider() LargeItemButton(R.string.activity_settings_privacy_button_title, R.drawable.ic_privacy_icon) { show() } Divider() diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt index 96fbec4270..121748809f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt @@ -16,7 +16,9 @@ import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import network.loki.messenger.R @@ -25,7 +27,9 @@ import org.thoughtcrime.securesms.ui.color.LocalColors class DialogButtonModel( val text: GetString, val contentDescription: GetString = text, - val onClick: () -> Unit + val color: Color = Color.Unspecified, + val dismissOnClick: Boolean = true, + val onClick: () -> Unit = {}, ) @Composable @@ -33,6 +37,7 @@ fun AlertDialog( onDismissRequest: () -> Unit, title: String? = null, text: String? = null, + content: @Composable () -> Unit = {}, buttons: List? = null ) { androidx.compose.material.AlertDialog( @@ -76,6 +81,7 @@ fun AlertDialog( modifier = Modifier.padding(bottom = LocalDimensions.current.xxsItemSpacing) ) } + content() } buttons?.takeIf { it.isNotEmpty() }?.let { Row(Modifier.height(IntrinsicSize.Min)) { @@ -85,10 +91,11 @@ fun AlertDialog( modifier = Modifier .fillMaxHeight() .contentDescription(it.contentDescription()) - .weight(1f) + .weight(1f), + color = it.color ) { it.onClick() - onDismissRequest() + if (it.dismissOnClick) onDismissRequest() } } } @@ -100,7 +107,7 @@ fun AlertDialog( } @Composable -fun DialogButton(text: String, modifier: Modifier, onClick: () -> Unit) { +fun DialogButton(text: String, modifier: Modifier, color: Color = Color.Unspecified, onClick: () -> Unit) { TextButton( modifier = modifier, shape = RectangleShape, @@ -108,7 +115,7 @@ fun DialogButton(text: String, modifier: Modifier, onClick: () -> Unit) { ) { Text( text, - color = LocalColors.current.text, + color = color.takeOrElse { LocalColors.current.text }, style = largeBold, textAlign = TextAlign.Center, modifier = Modifier.padding( diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt index 0ecc1124b1..31ce715a8f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -26,7 +26,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.ButtonColors import androidx.compose.material.Card -import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Icon import androidx.compose.material.LocalContentColor import androidx.compose.material.MaterialTheme @@ -69,6 +68,7 @@ import org.thoughtcrime.securesms.ui.color.LocalColors import org.thoughtcrime.securesms.ui.color.divider import org.thoughtcrime.securesms.ui.color.radioButtonColors import org.thoughtcrime.securesms.ui.color.transparentButtonColors +import org.thoughtcrime.securesms.ui.components.SmallCircularProgressIndicator import kotlin.math.min import kotlin.math.roundToInt @@ -453,11 +453,7 @@ fun LaunchedEffectAsync(block: suspend CoroutineScope.() -> Unit) { @Composable fun LoadingArcOr(loading: Boolean, content: @Composable () -> Unit) { AnimatedVisibility(loading) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp), - color = LocalContentColor.current, - strokeWidth = 2.dp - ) + SmallCircularProgressIndicator(color = LocalContentColor.current) } AnimatedVisibility(!loading) { content() diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/CircularProgressIndicator.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/CircularProgressIndicator.kt new file mode 100644 index 0000000000..259bbfe170 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/CircularProgressIndicator.kt @@ -0,0 +1,26 @@ +package org.thoughtcrime.securesms.ui.components + +import androidx.compose.foundation.layout.size +import androidx.compose.material.LocalContentColor +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +@Composable +fun CircularProgressIndicator(color: Color = LocalContentColor.current) { + androidx.compose.material.CircularProgressIndicator( + modifier = Modifier.size(40.dp), + color = color, + strokeWidth = 2.dp + ) +} + +@Composable +fun SmallCircularProgressIndicator(color: Color = LocalContentColor.current) { + androidx.compose.material.CircularProgressIndicator( + modifier = Modifier.size(20.dp), + color = color, + strokeWidth = 2.dp + ) +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3221fe9664..a6004f4837 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1140,4 +1140,7 @@ Copy button View QR code QR code + Warning + You cannot go back further. In order to stop loading your account, Session needs to quit. + Quit