[Room List] Show offline indicator when the device is offline (#239)
* Implement the network status indicator. * Add `networkmonitor` feature.
This commit is contained in:
parent
200763e15a
commit
d391275420
33 changed files with 511 additions and 21 deletions
|
|
@ -26,6 +26,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
|
|
@ -42,6 +43,7 @@ import io.element.android.libraries.matrix.api.room.RoomSummary
|
|||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -57,6 +59,7 @@ class RoomListPresenter @Inject constructor(
|
|||
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
|
||||
private val roomLastMessageFormatter: RoomLastMessageFormatter,
|
||||
private val sessionVerificationService: SessionVerificationService,
|
||||
private val networkMonitor: NetworkMonitor,
|
||||
private val snackbarDispatcher: SnackbarDispatcher,
|
||||
) : Presenter<RoomListState> {
|
||||
|
||||
|
|
@ -71,6 +74,8 @@ class RoomListPresenter @Inject constructor(
|
|||
.roomSummaries()
|
||||
.collectAsState()
|
||||
|
||||
val networkConnectionStatus by networkMonitor.connectivity.collectAsState(initial = networkMonitor.currentConnectivityStatus)
|
||||
|
||||
Timber.v("RoomSummaries size = ${roomSummaries.size}")
|
||||
|
||||
val filteredRoomSummaries: MutableState<ImmutableList<RoomListRoomSummary>> = remember {
|
||||
|
|
@ -108,6 +113,7 @@ class RoomListPresenter @Inject constructor(
|
|||
filter = filter,
|
||||
displayVerificationPrompt = displayVerificationPrompt,
|
||||
snackbarMessage = snackbarMessage,
|
||||
hasNetworkConnection = networkConnectionStatus == NetworkStatus.Online,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ data class RoomListState(
|
|||
val roomList: ImmutableList<RoomListRoomSummary>,
|
||||
val filter: String,
|
||||
val displayVerificationPrompt: Boolean,
|
||||
val hasNetworkConnection: Boolean,
|
||||
val snackbarMessage: SnackbarMessage?,
|
||||
val eventSink: (RoomListEvents) -> Unit
|
||||
)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
|
|||
aRoomListState(),
|
||||
aRoomListState().copy(displayVerificationPrompt = true),
|
||||
aRoomListState().copy(snackbarMessage = SnackbarMessage(StringR.string.common_verification_complete)),
|
||||
aRoomListState().copy(hasNetworkConnection = false),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ internal fun aRoomListState() = RoomListState(
|
|||
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("@id", "U")),
|
||||
roomList = aRoomListRoomSummaryList(),
|
||||
filter = "filter",
|
||||
hasNetworkConnection = true,
|
||||
snackbarMessage = null,
|
||||
displayVerificationPrompt = false,
|
||||
eventSink = {}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import io.element.android.libraries.designsystem.theme.components.Surface
|
|||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
|
||||
import kotlinx.coroutines.launch
|
||||
import io.element.android.libraries.designsystem.R as DrawableR
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
|
@ -150,14 +151,16 @@ fun RoomListContent(
|
|||
Scaffold(
|
||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
RoomListTopBar(
|
||||
matrixUser = state.matrixUser,
|
||||
filter = state.filter,
|
||||
onFilterChanged = { state.eventSink(RoomListEvents.UpdateFilter(it)) },
|
||||
onOpenSettings = onOpenSettings,
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier,
|
||||
)
|
||||
Column {
|
||||
ConnectivityIndicatorView(isOnline = state.hasNetworkConnection)
|
||||
RoomListTopBar(
|
||||
matrixUser = state.matrixUser,
|
||||
filter = state.filter,
|
||||
onFilterChanged = { state.eventSink(RoomListEvents.UpdateFilter(it)) },
|
||||
onOpenSettings = onOpenSettings,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
},
|
||||
content = { padding ->
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package io.element.android.features.roomlist.impl.components
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -46,6 +47,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.roomlist.impl.R
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
|
|
@ -172,6 +174,7 @@ fun SearchRoomListTopBar(
|
|||
)
|
||||
}
|
||||
},
|
||||
windowInsets = WindowInsets(0.dp)
|
||||
)
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
|
|
@ -231,6 +234,7 @@ private fun DefaultRoomListTopBar(
|
|||
}
|
||||
},
|
||||
scrollBehavior = scrollBehavior,
|
||||
windowInsets = WindowInsets(0.dp),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionClock
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
||||
|
|
@ -49,6 +50,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -76,6 +78,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -97,6 +100,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -122,6 +126,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -152,6 +157,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -187,6 +193,7 @@ class RoomListPresenterTests {
|
|||
createDateFormatter(),
|
||||
FakeRoomLastMessageFormatter(),
|
||||
FakeSessionVerificationService(),
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
@ -236,6 +243,7 @@ class RoomListPresenterTests {
|
|||
givenIsReady(true)
|
||||
givenVerifiedStatus(SessionVerifiedStatus.NotVerified)
|
||||
},
|
||||
FakeNetworkMonitor(),
|
||||
SnackbarDispatcher(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue