From a9a85bebf72170aff14618940eb1a70173bdef2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Mon, 16 Dec 2024 14:16:34 +0100 Subject: [PATCH] feat: Custom server no network dialog #WPB-11627 (#3543) --- .../com/wire/android/ui/WireActivity.kt | 18 +++++----- .../wire/android/ui/WireActivityDialogs.kt | 13 +++++--- .../wire/android/ui/WireActivityViewModel.kt | 21 +++++++----- ...alog.kt => CustomServerNoNetworkDialog.kt} | 33 ++++++++++++------- app/src/main/res/values-hu/strings.xml | 3 +- app/src/main/res/values-ru/strings.xml | 3 +- app/src/main/res/values/strings.xml | 5 +-- .../android/ui/WireActivityViewModelTest.kt | 16 ++++----- 8 files changed, 63 insertions(+), 49 deletions(-) rename app/src/main/kotlin/com/wire/android/ui/common/dialogs/{CustomServerInvalidJsonDialog.kt => CustomServerNoNetworkDialog.kt} (59%) diff --git a/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt b/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt index a95911f1af0..54d9e7ff6d6 100644 --- a/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt +++ b/app/src/main/kotlin/com/wire/android/ui/WireActivity.kt @@ -517,16 +517,14 @@ class WireActivity : AppCompatActivity() { ) CustomBackendDialog( viewModel.globalAppState, - viewModel::dismissCustomBackendDialog - ) { - viewModel.customBackendDialogProceedButtonClicked { - navigate( - NavigationCommand( - WelcomeScreenDestination - ) - ) - } - } + viewModel::dismissCustomBackendDialog, + onConfirm = { + viewModel.customBackendDialogProceedButtonClicked { + navigate(NavigationCommand(WelcomeScreenDestination)) + } + }, + onTryAgain = viewModel::onCustomServerConfig + ) MaxAccountDialog( shouldShow = viewModel.globalAppState.maxAccountDialog, onConfirm = { diff --git a/app/src/main/kotlin/com/wire/android/ui/WireActivityDialogs.kt b/app/src/main/kotlin/com/wire/android/ui/WireActivityDialogs.kt index 8b8ee6e66b3..564950de627 100644 --- a/app/src/main/kotlin/com/wire/android/ui/WireActivityDialogs.kt +++ b/app/src/main/kotlin/com/wire/android/ui/WireActivityDialogs.kt @@ -57,8 +57,8 @@ import com.wire.android.ui.common.button.WireButtonState import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.dialogs.CustomServerDetailsDialog import com.wire.android.ui.common.dialogs.CustomServerDetailsDialogState -import com.wire.android.ui.common.dialogs.CustomServerInvalidJsonDialog -import com.wire.android.ui.common.dialogs.CustomServerInvalidJsonDialogState +import com.wire.android.ui.common.dialogs.CustomServerNoNetworkDialog +import com.wire.android.ui.common.dialogs.CustomServerNoNetworkDialogState import com.wire.android.ui.common.dialogs.MaxAccountAllowedDialogContent import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.wireDialogPropertiesBuilder @@ -244,7 +244,8 @@ fun JoinConversationDialog( fun CustomBackendDialog( globalAppState: GlobalAppState, onDismiss: () -> Unit, - onConfirm: () -> Unit + onConfirm: () -> Unit, + onTryAgain: (String) -> Unit ) { when (globalAppState.customBackendDialog) { is CustomServerDetailsDialogState -> { @@ -255,8 +256,9 @@ fun CustomBackendDialog( ) } - is CustomServerInvalidJsonDialogState -> { - CustomServerInvalidJsonDialog( + is CustomServerNoNetworkDialogState -> { + CustomServerNoNetworkDialog( + onTryAgain = { onTryAgain(globalAppState.customBackendDialog.customServerUrl) }, onDismiss = onDismiss ) } @@ -581,6 +583,7 @@ fun PreviewCustomBackendDialog() { ) ), {}, + {}, {} ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt index d4ee4acfd2b..fc173d079cb 100644 --- a/app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt @@ -42,7 +42,7 @@ import com.wire.android.services.ServicesManager import com.wire.android.ui.authentication.devices.model.displayName import com.wire.android.ui.common.dialogs.CustomServerDetailsDialogState import com.wire.android.ui.common.dialogs.CustomServerDialogState -import com.wire.android.ui.common.dialogs.CustomServerInvalidJsonDialogState +import com.wire.android.ui.common.dialogs.CustomServerNoNetworkDialogState import com.wire.android.ui.joinConversation.JoinConversationViaCodeState import com.wire.android.ui.theme.ThemeOption import com.wire.android.util.CurrentScreen @@ -320,7 +320,7 @@ class WireActivityViewModel @Inject constructor( when (val result = deepLinkProcessor.get().invoke(intent?.data, isSharingIntent)) { DeepLinkResult.AuthorizationNeeded -> onAuthorizationNeeded() is DeepLinkResult.SSOLogin -> onSSOLogin(result) - is DeepLinkResult.CustomServerConfig -> onCustomServerConfig(result) + is DeepLinkResult.CustomServerConfig -> onCustomServerConfig(result.url) is DeepLinkResult.Failure.OngoingCall -> onCannotLoginDuringACall() is DeepLinkResult.Failure.Unknown -> appLogger.e("unknown deeplink failure") is DeepLinkResult.JoinConversation -> onConversationInviteDeepLink( @@ -429,13 +429,16 @@ class WireActivityViewModel @Inject constructor( } } - private suspend fun onCustomServerConfig(result: DeepLinkResult.CustomServerConfig) { - val customBackendDialogData = loadServerConfig(result.url)?.let { serverLinks -> - CustomServerDetailsDialogState(serverLinks = serverLinks) - } ?: CustomServerInvalidJsonDialogState - globalAppState = globalAppState.copy( - customBackendDialog = customBackendDialogData - ) + fun onCustomServerConfig(customServerUrl: String) { + viewModelScope.launch(dispatchers.io()) { + val customBackendDialogData = loadServerConfig(customServerUrl) + ?.let { serverLinks -> CustomServerDetailsDialogState(serverLinks = serverLinks) } + ?: CustomServerNoNetworkDialogState(customServerUrl) + + globalAppState = globalAppState.copy( + customBackendDialog = customBackendDialogData + ) + } } private suspend fun onConversationInviteDeepLink( diff --git a/app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerInvalidJsonDialog.kt b/app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerNoNetworkDialog.kt similarity index 59% rename from app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerInvalidJsonDialog.kt rename to app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerNoNetworkDialog.kt index 356d9b12f17..1ad8d752f0b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerInvalidJsonDialog.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/dialogs/CustomServerNoNetworkDialog.kt @@ -28,29 +28,40 @@ import com.wire.android.ui.theme.WireTheme import com.wire.android.util.ui.PreviewMultipleThemes @Composable -internal fun CustomServerInvalidJsonDialog( +internal fun CustomServerNoNetworkDialog( + onTryAgain: () -> Unit, onDismiss: () -> Unit ) { WireDialog( - title = stringResource(R.string.custom_backend_invalid_deeplink_data_title), - text = stringResource(R.string.custom_backend_invalid_deeplink_data_body), + title = stringResource(R.string.custom_backend_error_title), + text = stringResource(R.string.custom_backend_error_no_internet_connection_body), onDismiss = onDismiss, + buttonsHorizontalAlignment = false, optionButton1Properties = WireDialogButtonProperties( - onClick = onDismiss, - text = stringResource(id = R.string.label_ok), + onClick = { + onTryAgain() + onDismiss() + }, + text = stringResource(id = R.string.custom_backend_error_no_internet_connection_try_again), type = WireDialogButtonType.Primary, - state = - WireButtonState.Default + state = WireButtonState.Default ), + optionButton2Properties = WireDialogButtonProperties( + onClick = onDismiss, + text = stringResource(id = R.string.label_cancel), + type = WireDialogButtonType.Secondary, + state = WireButtonState.Default + ) ) } -data object CustomServerInvalidJsonDialogState : CustomServerDialogState() +data class CustomServerNoNetworkDialogState(val customServerUrl: String) : CustomServerDialogState() @PreviewMultipleThemes @Composable -fun PreviewCustomServerInvalidJsonDialog() = WireTheme { - CustomServerInvalidJsonDialog( - onDismiss = { } +fun PreviewCustomServerNoNetworkDialog() = WireTheme { + CustomServerNoNetworkDialog( + onTryAgain = {}, + onDismiss = {} ) } diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index ff5e1b7e98a..57ed2e7001d 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -1133,8 +1133,7 @@ Ez a beállítás az összes beszélgetésre érvényes ezen az eszközön.Fiókok URL: Honlap URL: Kiszolgáló WSURL: - Hiba történt - A saját kiszolgálóra történő átirányítás nem volt lehetséges, mivel a JSON fájl érvénytelen beállítást tartalmazott.\n\nLépjen kapcsolatba a rendszergazdával, vagy ellenőrizze a mélylinket, ami ide vezette. + Hiba történt Új üzenetek lekérdezése Szöveg a vágólapra másolva Naplók diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8dfcce63cb6..99ecf9a8a1b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1171,8 +1171,7 @@ URL аккаунта: URL веб-сайта: WSURL бэкэнда: - Произошла ошибка - Перенаправление на локальный бэкэнд было неудачным, поскольку в JSON-файле была неверная конфигурация.\n\nСвяжитесь с администратором или проверьте ссылку, которая привела вас сюда. + Произошла ошибка Получение новых сообщений Текст скопирован в буфер обмена Журналы diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 718e9d41961..4811da7ef86 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1183,8 +1183,9 @@ In group conversations, the group admin can overwrite this setting. Accounts URL: Website URL: Backend WSURL: - An error occurred - Redirecting to an on-premises backend was not possible, as there was an invalid configuration in the JSON file.\n\nContact your admin or check the deeplink that brought you here. + An error occurred + Redirecting to an on-premises backend was not possible, you don’t seem to be connected to the internet.\n\nEstablish an internet connection and try again. + Try again Receiving new messages Text copied to clipboard Logs diff --git a/app/src/test/kotlin/com/wire/android/ui/WireActivityViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/WireActivityViewModelTest.kt index 6169a00d52f..f7070a642bf 100644 --- a/app/src/test/kotlin/com/wire/android/ui/WireActivityViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/WireActivityViewModelTest.kt @@ -38,7 +38,7 @@ import com.wire.android.framework.TestUser import com.wire.android.migration.MigrationManager import com.wire.android.services.ServicesManager import com.wire.android.ui.common.dialogs.CustomServerDetailsDialogState -import com.wire.android.ui.common.dialogs.CustomServerInvalidJsonDialogState +import com.wire.android.ui.common.dialogs.CustomServerNoNetworkDialogState import com.wire.android.ui.common.topappbar.CommonTopAppBarViewModelTest import com.wire.android.ui.joinConversation.JoinConversationViaCodeState import com.wire.android.ui.theme.ThemeOption @@ -141,13 +141,13 @@ class WireActivityViewModelTest { } @Test - fun `given Intent with malformed ServerConfig json, when currentSessions is present, then initialAppState is LOGGED_IN and customBackEndInvalidJson dialog is shown`() = + fun `given intent with correct ServerConfig json, when no network is present, then initialAppState is LOGGED_IN and no network dialog is shown`() = runTest { val result = DeepLinkResult.CustomServerConfig("url") val (arrangement, viewModel) = Arrangement() .withSomeCurrentSession() .withDeepLinkResult(result) - .withMalformedServerJson() + .withNoNetworkConnectionWhenGettingServerConfig() .withNoOngoingCall() .arrange() @@ -155,17 +155,17 @@ class WireActivityViewModelTest { assertEquals(InitialAppState.LOGGED_IN, viewModel.initialAppState()) verify(exactly = 0) { arrangement.onDeepLinkResult(any()) } - assertInstanceOf(CustomServerInvalidJsonDialogState::class.java, viewModel.globalAppState.customBackendDialog) + assertInstanceOf(CustomServerNoNetworkDialogState::class.java, viewModel.globalAppState.customBackendDialog) } @Test - fun `given Intent with malformed ServerConfig json, when currentSessions is present, then initialAppState is NOT_LOGGED_IN and customBackEndInvalidJson dialog is shown`() = + fun `given Intent with malformed ServerConfig json, when currentSessions is absent, then initialAppState is NOT_LOGGED_IN and no network dialog is shown`() = runTest { val result = DeepLinkResult.CustomServerConfig("url") val (arrangement, viewModel) = Arrangement() .withNoCurrentSession() .withDeepLinkResult(result) - .withMalformedServerJson() + .withNoNetworkConnectionWhenGettingServerConfig() .withNoOngoingCall() .arrange() @@ -173,7 +173,7 @@ class WireActivityViewModelTest { assertEquals(InitialAppState.NOT_LOGGED_IN, viewModel.initialAppState()) verify(exactly = 0) { arrangement.onDeepLinkResult(any()) } - assertInstanceOf(CustomServerInvalidJsonDialogState::class.java, viewModel.globalAppState.customBackendDialog) + assertInstanceOf(CustomServerNoNetworkDialogState::class.java, viewModel.globalAppState.customBackendDialog) } @Test @@ -919,7 +919,7 @@ class WireActivityViewModelTest { coEvery { coreLogic.getSessionScope(TEST_ACCOUNT_INFO.userId).observeIfE2EIRequiredDuringLogin() } returns flowOf(false) } - fun withMalformedServerJson() = apply { + fun withNoNetworkConnectionWhenGettingServerConfig() = apply { coEvery { getServerConfigUseCase(any()) } returns GetServerConfigResult.Failure.Generic(NetworkFailure.NoNetworkConnection(null)) }