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))
}
diff --git a/core/analytics-enabled/src/main/kotlin/com/wire/android/feature/analytics/AnonymousAnalyticsRecorderImpl.kt b/core/analytics-enabled/src/main/kotlin/com/wire/android/feature/analytics/AnonymousAnalyticsRecorderImpl.kt
index 0bb72c5545d..71fe3723667 100644
--- a/core/analytics-enabled/src/main/kotlin/com/wire/android/feature/analytics/AnonymousAnalyticsRecorderImpl.kt
+++ b/core/analytics-enabled/src/main/kotlin/com/wire/android/feature/analytics/AnonymousAnalyticsRecorderImpl.kt
@@ -20,6 +20,7 @@ package com.wire.android.feature.analytics
import android.app.Activity
import android.app.Application
import android.content.Context
+import android.util.Log
import com.wire.android.feature.analytics.model.AnalyticsEvent
import com.wire.android.feature.analytics.model.AnalyticsEventConstants
import com.wire.android.feature.analytics.model.AnalyticsSettings
@@ -34,8 +35,8 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
override fun configure(
context: Context,
analyticsSettings: AnalyticsSettings
- ) {
- if (isConfigured) return
+ ) = wrapCountlyRequest {
+ if (isConfigured) return@wrapCountlyRequest
val countlyConfig = CountlyConfig(
context,
@@ -54,24 +55,24 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
}
}
- Countly.sharedInstance().init(countlyConfig)
- Countly.sharedInstance().consent().giveConsent(arrayOf("apm"))
+ Countly.sharedInstance()?.init(countlyConfig)
+ Countly.sharedInstance()?.consent()?.giveConsent(arrayOf("apm"))
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
val globalSegmentations = mapOf(
AnalyticsEventConstants.APP_NAME to AnalyticsEventConstants.APP_NAME_ANDROID,
AnalyticsEventConstants.APP_VERSION to packageInfo.versionName
)
- Countly.sharedInstance().views().setGlobalViewSegmentation(globalSegmentations)
+ Countly.sharedInstance()?.views()?.setGlobalViewSegmentation(globalSegmentations)
isConfigured = true
}
- override fun onStart(activity: Activity) {
- Countly.sharedInstance().onStart(activity)
+ override fun onStart(activity: Activity) = wrapCountlyRequest {
+ Countly.sharedInstance()?.onStart(activity)
}
- override fun onStop() {
- Countly.sharedInstance().onStop()
+ override fun onStop() = wrapCountlyRequest {
+ Countly.sharedInstance()?.onStop()
}
/**
@@ -79,11 +80,11 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
* Countly is doing additional operations on it.
* See [UtilsInternalLimits.removeUnsupportedDataTypes]
*/
- override fun sendEvent(event: AnalyticsEvent) {
- Countly.sharedInstance().events().recordEvent(event.key, event.toSegmentation().toMutableMap())
+ override fun sendEvent(event: AnalyticsEvent) = wrapCountlyRequest {
+ Countly.sharedInstance()?.events()?.recordEvent(event.key, event.toSegmentation().toMutableMap())
}
- override fun halt() {
+ override fun halt() = wrapCountlyRequest {
isConfigured = false
Countly.sharedInstance().consent().removeConsentAll()
}
@@ -93,7 +94,9 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
isTeamMember: Boolean,
migrationComplete: suspend () -> Unit
) {
- Countly.sharedInstance().deviceId().changeWithMerge(identifier).also {
+ wrapCountlyRequest {
+ Countly.sharedInstance()?.deviceId()?.changeWithMerge(identifier)
+ }.also {
migrationComplete()
}
@@ -106,7 +109,9 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
isTeamMember: Boolean,
propagateIdentifier: suspend () -> Unit
) {
- Countly.sharedInstance().deviceId().changeWithoutMerge(identifier)
+ wrapCountlyRequest {
+ Countly.sharedInstance()?.deviceId()?.changeWithoutMerge(identifier)
+ }
setUserProfileProperties(isTeamMember = isTeamMember)
@@ -115,27 +120,42 @@ class AnonymousAnalyticsRecorderImpl : AnonymousAnalyticsRecorder {
}
}
- private fun setUserProfileProperties(isTeamMember: Boolean) {
- Countly.sharedInstance().userProfile().setProperty(
+ private fun setUserProfileProperties(isTeamMember: Boolean) = wrapCountlyRequest {
+ Countly.sharedInstance()?.userProfile()?.setProperty(
AnalyticsEventConstants.TEAM_IS_TEAM,
isTeamMember
)
- Countly.sharedInstance().userProfile().save()
+ Countly.sharedInstance()?.userProfile()?.save()
}
override fun isAnalyticsInitialized(): Boolean = Countly.sharedInstance().isInitialized
- override fun applicationOnCreate() {
- if (isConfigured) return
+ override fun applicationOnCreate() = wrapCountlyRequest {
+ if (isConfigured) return@wrapCountlyRequest
Countly.applicationOnCreate()
}
- override fun recordView(screen: String) {
- Countly.sharedInstance().views().startAutoStoppedView(screen)
+ override fun recordView(screen: String) = wrapCountlyRequest {
+ Countly.sharedInstance()?.views()?.startAutoStoppedView(screen)
+ }
+
+ override fun stopView(screen: String) = wrapCountlyRequest {
+ Countly.sharedInstance()?.views()?.stopViewWithName(screen)
+ }
+
+ @Suppress("TooGenericExceptionCaught")
+ private fun wrapCountlyRequest(block: () -> Unit) {
+ try {
+ block()
+ } catch (e: Exception) {
+ // Countly SDK throws exceptions on some cases, just log it
+ // We don't want to crash the app because of that.
+ Log.wtf(TAG, "Countly SDK request failed", e)
+ }
}
- override fun stopView(screen: String) {
- Countly.sharedInstance().views().stopViewWithName(screen)
+ companion object {
+ private const val TAG = "AnonymousAnalyticsRecorderImpl"
}
}