mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 21:32:34 +00:00
Merge pull request #7567 from hayaksi1/fix/4099-server-unreachable
Say when the server cannot be reached instead of showing nothing
This commit is contained in:
@@ -105,9 +105,18 @@ class LoggedInPresenter(
|
|||||||
}
|
}
|
||||||
val syncIndicator by matrixClient.roomListService.syncIndicator.collectAsState()
|
val syncIndicator by matrixClient.roomListService.syncIndicator.collectAsState()
|
||||||
val isOnline by syncService.isOnline.collectAsState()
|
val isOnline by syncService.isOnline.collectAsState()
|
||||||
val showSyncSpinner by remember {
|
val hasNetwork by networkMonitor.connectivity.collectAsState()
|
||||||
|
val syncIndicatorState by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
isOnline && syncIndicator == RoomListService.SyncIndicator.Show
|
when {
|
||||||
|
isOnline -> if (syncIndicator == RoomListService.SyncIndicator.Show) {
|
||||||
|
SyncIndicatorState.Syncing
|
||||||
|
} else {
|
||||||
|
SyncIndicatorState.Hidden
|
||||||
|
}
|
||||||
|
hasNetwork == NetworkStatus.Connected -> SyncIndicatorState.ServerUnreachable
|
||||||
|
else -> SyncIndicatorState.Hidden
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var forceNativeSlidingSyncMigration by remember { mutableStateOf(false) }
|
var forceNativeSlidingSyncMigration by remember { mutableStateOf(false) }
|
||||||
@@ -181,7 +190,7 @@ class LoggedInPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return LoggedInState(
|
return LoggedInState(
|
||||||
showSyncSpinner = showSyncSpinner,
|
syncIndicatorState = syncIndicatorState,
|
||||||
pusherRegistrationState = pusherRegistrationState.value,
|
pusherRegistrationState = pusherRegistrationState.value,
|
||||||
ignoreRegistrationError = ignoreRegistrationError,
|
ignoreRegistrationError = ignoreRegistrationError,
|
||||||
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
||||||
|
|||||||
@@ -11,8 +11,14 @@ package io.element.android.appnav.loggedin
|
|||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog
|
import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog
|
||||||
|
|
||||||
|
enum class SyncIndicatorState {
|
||||||
|
Hidden,
|
||||||
|
Syncing,
|
||||||
|
ServerUnreachable,
|
||||||
|
}
|
||||||
|
|
||||||
data class LoggedInState(
|
data class LoggedInState(
|
||||||
val showSyncSpinner: Boolean,
|
val syncIndicatorState: SyncIndicatorState,
|
||||||
val pusherRegistrationState: AsyncData<Unit>,
|
val pusherRegistrationState: AsyncData<Unit>,
|
||||||
val ignoreRegistrationError: Boolean,
|
val ignoreRegistrationError: Boolean,
|
||||||
val forceNativeSlidingSyncMigration: Boolean,
|
val forceNativeSlidingSyncMigration: Boolean,
|
||||||
|
|||||||
+4
-3
@@ -17,7 +17,8 @@ open class LoggedInStatePreviewParam : PreviewParameterProvider<LoggedInState> {
|
|||||||
override val values: Sequence<LoggedInState>
|
override val values: Sequence<LoggedInState>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
aLoggedInState(),
|
aLoggedInState(),
|
||||||
aLoggedInState(showSyncSpinner = true),
|
aLoggedInState(syncIndicatorState = SyncIndicatorState.Syncing),
|
||||||
|
aLoggedInState(syncIndicatorState = SyncIndicatorState.ServerUnreachable),
|
||||||
aLoggedInState(pusherRegistrationState = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable())),
|
aLoggedInState(pusherRegistrationState = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable())),
|
||||||
aLoggedInState(forceNativeSlidingSyncMigration = true),
|
aLoggedInState(forceNativeSlidingSyncMigration = true),
|
||||||
aLoggedInState(localNetworkPermissionDialog = LocalNetworkPermissionDialog.Rationale),
|
aLoggedInState(localNetworkPermissionDialog = LocalNetworkPermissionDialog.Rationale),
|
||||||
@@ -26,13 +27,13 @@ open class LoggedInStatePreviewParam : PreviewParameterProvider<LoggedInState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun aLoggedInState(
|
fun aLoggedInState(
|
||||||
showSyncSpinner: Boolean = false,
|
syncIndicatorState: SyncIndicatorState = SyncIndicatorState.Hidden,
|
||||||
pusherRegistrationState: AsyncData<Unit> = AsyncData.Uninitialized,
|
pusherRegistrationState: AsyncData<Unit> = AsyncData.Uninitialized,
|
||||||
forceNativeSlidingSyncMigration: Boolean = false,
|
forceNativeSlidingSyncMigration: Boolean = false,
|
||||||
appName: String = "Element X",
|
appName: String = "Element X",
|
||||||
localNetworkPermissionDialog: LocalNetworkPermissionDialog = LocalNetworkPermissionDialog.None,
|
localNetworkPermissionDialog: LocalNetworkPermissionDialog = LocalNetworkPermissionDialog.None,
|
||||||
) = LoggedInState(
|
) = LoggedInState(
|
||||||
showSyncSpinner = showSyncSpinner,
|
syncIndicatorState = syncIndicatorState,
|
||||||
pusherRegistrationState = pusherRegistrationState,
|
pusherRegistrationState = pusherRegistrationState,
|
||||||
ignoreRegistrationError = false,
|
ignoreRegistrationError = false,
|
||||||
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ fun LoggedInView(
|
|||||||
) {
|
) {
|
||||||
SyncStateView(
|
SyncStateView(
|
||||||
modifier = Modifier.align(Alignment.TopCenter),
|
modifier = Modifier.align(Alignment.TopCenter),
|
||||||
isVisible = state.showSyncSpinner,
|
state = state.syncIndicatorState,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
when (state.pusherRegistrationState) {
|
when (state.pusherRegistrationState) {
|
||||||
|
|||||||
@@ -25,18 +25,23 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SyncStateView(
|
fun SyncStateView(
|
||||||
isVisible: Boolean,
|
state: SyncIndicatorState,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = isVisible,
|
visible = state != SyncIndicatorState.Hidden,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
enter = fadeIn(spring(stiffness = 500F)),
|
enter = fadeIn(spring(stiffness = 500F)),
|
||||||
exit = fadeOut(spring(stiffness = 500F)),
|
exit = fadeOut(spring(stiffness = 500F)),
|
||||||
) {
|
) {
|
||||||
AsyncIndicator.Loading(
|
when (state) {
|
||||||
text = stringResource(id = CommonStrings.common_syncing),
|
SyncIndicatorState.ServerUnreachable -> AsyncIndicator.Failure(
|
||||||
)
|
text = stringResource(id = CommonStrings.common_server_unreachable),
|
||||||
|
)
|
||||||
|
else -> AsyncIndicator.Loading(
|
||||||
|
text = stringResource(id = CommonStrings.common_syncing),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +51,18 @@ internal fun SyncStateViewPreview() = ElementPreview {
|
|||||||
// Add a box to see the shadow
|
// Add a box to see the shadow
|
||||||
Box(modifier = Modifier.padding(24.dp)) {
|
Box(modifier = Modifier.padding(24.dp)) {
|
||||||
SyncStateView(
|
SyncStateView(
|
||||||
isVisible = true
|
state = SyncIndicatorState.Syncing
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreviewsDayNight
|
||||||
|
@Composable
|
||||||
|
internal fun SyncStateViewServerUnreachablePreview() = ElementPreview {
|
||||||
|
// Add a box to see the shadow
|
||||||
|
Box(modifier = Modifier.padding(24.dp)) {
|
||||||
|
SyncStateView(
|
||||||
|
state = SyncIndicatorState.ServerUnreachable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class LoggedInPresenterTest {
|
|||||||
fun `present - initial state`() = runTest {
|
fun `present - initial state`() = runTest {
|
||||||
createLoggedInPresenter().test {
|
createLoggedInPresenter().test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.showSyncSpinner).isFalse()
|
assertThat(initialState.syncIndicatorState).isEqualTo(SyncIndicatorState.Hidden)
|
||||||
assertThat(initialState.pusherRegistrationState.isUninitialized()).isTrue()
|
assertThat(initialState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||||
assertThat(initialState.ignoreRegistrationError).isFalse()
|
assertThat(initialState.ignoreRegistrationError).isFalse()
|
||||||
}
|
}
|
||||||
@@ -97,11 +97,33 @@ class LoggedInPresenterTest {
|
|||||||
matrixClient = FakeMatrixClient(roomListService = roomListService),
|
matrixClient = FakeMatrixClient(roomListService = roomListService),
|
||||||
).test {
|
).test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.showSyncSpinner).isFalse()
|
assertThat(initialState.syncIndicatorState).isEqualTo(SyncIndicatorState.Hidden)
|
||||||
roomListService.postSyncIndicator(RoomListService.SyncIndicator.Show)
|
roomListService.postSyncIndicator(RoomListService.SyncIndicator.Show)
|
||||||
consumeItemsUntilPredicate { it.showSyncSpinner }
|
consumeItemsUntilPredicate { it.syncIndicatorState == SyncIndicatorState.Syncing }
|
||||||
roomListService.postSyncIndicator(RoomListService.SyncIndicator.Hide)
|
roomListService.postSyncIndicator(RoomListService.SyncIndicator.Hide)
|
||||||
consumeItemsUntilPredicate { !it.showSyncSpinner }
|
consumeItemsUntilPredicate { it.syncIndicatorState != SyncIndicatorState.Syncing }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - say the server is unreachable when the device has network but the sync is offline`() = runTest {
|
||||||
|
createLoggedInPresenter(
|
||||||
|
syncState = SyncState.Offline,
|
||||||
|
networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Connected),
|
||||||
|
).test {
|
||||||
|
consumeItemsUntilPredicate { it.syncIndicatorState == SyncIndicatorState.ServerUnreachable }
|
||||||
|
cancelAndConsumeRemainingEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - say nothing when the device itself has no network`() = runTest {
|
||||||
|
createLoggedInPresenter(
|
||||||
|
syncState = SyncState.Offline,
|
||||||
|
networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Disconnected),
|
||||||
|
).test {
|
||||||
|
consumeItemsUntilPredicate { it.syncIndicatorState == SyncIndicatorState.Hidden }
|
||||||
|
cancelAndConsumeRemainingEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class KonsistPreviewTest {
|
|||||||
"SecureBackupSetupViewChangePreview",
|
"SecureBackupSetupViewChangePreview",
|
||||||
"SelectedUserCannotRemovePreview",
|
"SelectedUserCannotRemovePreview",
|
||||||
"SpaceMembersViewNoHeroesPreview",
|
"SpaceMembersViewNoHeroesPreview",
|
||||||
|
"SyncStateViewServerUnreachablePreview",
|
||||||
"TextComposerAddCaptionPreview",
|
"TextComposerAddCaptionPreview",
|
||||||
"TextComposerCaptionPreview",
|
"TextComposerCaptionPreview",
|
||||||
"TextComposerEditCaptionPreview",
|
"TextComposerEditCaptionPreview",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user