From 597081e9a8fad521b454eb4a256b16c7b60f736e Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Tue, 21 Feb 2023 15:22:08 +0100
Subject: [PATCH 01/14] Adding unread counter badge view
---
.../res/layout/fragment_new_home_detail.xml | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/vector/src/main/res/layout/fragment_new_home_detail.xml b/vector/src/main/res/layout/fragment_new_home_detail.xml
index ced71a7863..8f603e57ab 100644
--- a/vector/src/main/res/layout/fragment_new_home_detail.xml
+++ b/vector/src/main/res/layout/fragment_new_home_detail.xml
@@ -120,6 +120,28 @@
tools:targetApi="lollipop_mr1"
tools:visibility="visible" />
+
+
Date: Tue, 21 Feb 2023 16:28:30 +0100
Subject: [PATCH 02/14] Use case to compute the notification counter for spaces
---
.../app/features/spaces/SpaceListViewModel.kt | 37 ++--------
.../GetNotificationCountForSpacesUseCase.kt | 70 +++++++++++++++++++
2 files changed, 74 insertions(+), 33 deletions(-)
create mode 100644 vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
index 99f6a254b8..e5ebce0c11 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
@@ -32,13 +32,11 @@ import im.vector.app.features.analytics.plan.Interaction
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
-import kotlinx.coroutines.Dispatchers
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.query.QueryStringValue
@@ -48,12 +46,9 @@ import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getUserOrDefault
-import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataTypes
import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
-import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
import org.matrix.android.sdk.api.session.space.SpaceOrderUtils
import org.matrix.android.sdk.api.session.space.model.SpaceOrderContent
import org.matrix.android.sdk.api.session.space.model.TopLevelSpaceComparator
@@ -67,6 +62,7 @@ class SpaceListViewModel @AssistedInject constructor(
private val vectorPreferences: VectorPreferences,
private val autoAcceptInvites: AutoAcceptInvites,
private val analyticsTracker: AnalyticsTracker,
+ private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
) : VectorViewModel(initialState) {
@AssistedFactory
@@ -92,39 +88,14 @@ class SpaceListViewModel @AssistedInject constructor(
copy(selectedSpace = selectedSpaceOption.orNull())
}
- // XXX there should be a way to refactor this and share it
- session.roomService().getPagedRoomSummariesLive(
- roomSummaryQueryParams {
- this.memberships = listOf(Membership.JOIN)
- this.spaceFilter = roomsInSpaceFilter()
- }, sortOrder = RoomSortOrder.NONE
- ).asFlow()
- .sample(300)
- .onEach {
- val inviteCount = if (autoAcceptInvites.hideInvites) {
- 0
- } else {
- session.roomService().getRoomSummaries(
- roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
- ).size
- }
- val totalCount = session.roomService().getNotificationCountForRooms(
- roomSummaryQueryParams {
- this.memberships = listOf(Membership.JOIN)
- this.spaceFilter = roomsInSpaceFilter()
- }
- )
- val counts = RoomAggregateNotificationCount(
- totalCount.notificationCount + inviteCount,
- totalCount.highlightCount + inviteCount
- )
+ getNotificationCountForSpacesUseCase.execute(roomsInSpaceFilter())
+ .onEach { counts ->
setState {
copy(
homeAggregateCount = counts
)
}
}
- .flowOn(Dispatchers.Default)
.launchIn(viewModelScope)
}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
new file mode 100644
index 0000000000..5f79619c92
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.spaces.notification
+
+import androidx.lifecycle.asFlow
+import im.vector.app.core.di.ActiveSessionHolder
+import im.vector.app.features.invite.AutoAcceptInvites
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.sample
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+import javax.inject.Inject
+
+// TODO add unit tests
+class GetNotificationCountForSpacesUseCase @Inject constructor(
+ private val activeSessionHolder: ActiveSessionHolder,
+ private val autoAcceptInvites: AutoAcceptInvites,
+) {
+
+ fun execute(spaceFilter: SpaceFilter): Flow {
+ val session = activeSessionHolder.getSafeActiveSession()
+
+ val spaceQueryParams = roomSummaryQueryParams {
+ this.memberships = listOf(Membership.JOIN)
+ this.spaceFilter = spaceFilter
+ }
+ return session
+ ?.roomService()
+ ?.getPagedRoomSummariesLive(queryParams = spaceQueryParams, sortOrder = RoomSortOrder.NONE)
+ ?.asFlow()
+ ?.sample(300)
+ ?.mapLatest {
+ val inviteCount = if (autoAcceptInvites.hideInvites) {
+ 0
+ } else {
+ session.roomService().getRoomSummaries(
+ roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
+ ).size
+ }
+ val totalCount = session.roomService().getNotificationCountForRooms(spaceQueryParams)
+ RoomAggregateNotificationCount(
+ notificationCount = totalCount.notificationCount + inviteCount,
+ highlightCount = totalCount.highlightCount + inviteCount,
+ )
+ }
+ ?.flowOn(Dispatchers.Default)
+ ?: emptyFlow()
+ }
+}
From 0e8a2254f8a7e8dbd2ed5d8430773962d736351d Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Tue, 21 Feb 2023 17:44:31 +0100
Subject: [PATCH 03/14] Listen for spaces notification count to refresh the
badge
---
.../app/core/di/MavericksViewModelModule.kt | 6 ++
.../features/home/NewHomeDetailFragment.kt | 15 +++++
.../features/home/NewHomeDetailViewModel.kt | 60 +++++++++++++++++++
.../features/home/NewHomeDetailViewState.kt | 24 ++++++++
4 files changed, 105 insertions(+)
create mode 100644 vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
create mode 100644 vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
index 35d8d0e896..27981c3d36 100644
--- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
@@ -40,6 +40,7 @@ import im.vector.app.features.discovery.DiscoverySettingsViewModel
import im.vector.app.features.discovery.change.SetIdentityServerViewModel
import im.vector.app.features.home.HomeActivityViewModel
import im.vector.app.features.home.HomeDetailViewModel
+import im.vector.app.features.home.NewHomeDetailViewModel
import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel
import im.vector.app.features.home.UnreadMessagesSharedViewModel
import im.vector.app.features.home.UserColorAccountDataViewModel
@@ -717,4 +718,9 @@ interface MavericksViewModelModule {
@IntoMap
@MavericksViewModelKey(RoomPollDetailViewModel::class)
fun roomPollDetailViewModelFactory(factory: RoomPollDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(NewHomeDetailViewModel::class)
+ fun newHomeDetailViewModelFactory(factory: NewHomeDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
index 3189c2b99e..ff995311e6 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
@@ -47,6 +47,7 @@ import im.vector.app.features.call.SharedKnownCallsViewModel
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.dialpad.PstnDialActivity
import im.vector.app.features.call.webrtc.WebRtcCallManager
+import im.vector.app.features.home.room.list.UnreadCounterBadgeView
import im.vector.app.features.home.room.list.actions.RoomListSharedAction
import im.vector.app.features.home.room.list.actions.RoomListSharedActionViewModel
import im.vector.app.features.home.room.list.home.HomeRoomListFragment
@@ -63,6 +64,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
import javax.inject.Inject
@AndroidEntryPoint
@@ -82,6 +84,7 @@ class NewHomeDetailFragment :
@Inject lateinit var buildMeta: BuildMeta
private val viewModel: HomeDetailViewModel by fragmentViewModel()
+ private val newHomeDetailViewModel: NewHomeDetailViewModel by fragmentViewModel()
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
private val serverBackupStatusViewModel: ServerBackupStatusViewModel by activityViewModel()
@@ -180,6 +183,10 @@ class NewHomeDetailFragment :
currentCallsViewPresenter.updateCall(callManager.getCurrentCall(), callManager.getCalls())
invalidateOptionsMenu()
}
+
+ newHomeDetailViewModel.onEach { viewState ->
+ refreshUnreadCounterBadge(viewState.spacesNotificationCount)
+ }
}
private fun setupObservers() {
@@ -379,6 +386,14 @@ class NewHomeDetailFragment :
}
}
+ private fun refreshUnreadCounterBadge(roomAggregateNotificationCount: RoomAggregateNotificationCount) {
+ val badgeState = UnreadCounterBadgeView.State.Count(
+ count = roomAggregateNotificationCount.notificationCount,
+ highlighted = roomAggregateNotificationCount.isHighlight,
+ )
+ views.spacesUnreadCounterBadge.render(badgeState)
+ }
+
override fun onTapToReturnToCall() {
callManager.getCurrentCall()?.let { call ->
VectorCallActivity.newIntent(
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
new file mode 100644
index 0000000000..6f3ba79cf8
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home
+
+import com.airbnb.mvrx.MavericksViewModelFactory
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import im.vector.app.core.di.MavericksAssistedViewModelFactory
+import im.vector.app.core.di.hiltMavericksViewModelFactory
+import im.vector.app.core.platform.EmptyAction
+import im.vector.app.core.platform.EmptyViewEvents
+import im.vector.app.core.platform.VectorViewModel
+import im.vector.app.features.roomprofile.polls.RoomPollsViewModel
+import im.vector.app.features.roomprofile.polls.RoomPollsViewState
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.matrix.android.sdk.api.query.SpaceFilter
+
+class NewHomeDetailViewModel @AssistedInject constructor(
+ @Assisted initialState: NewHomeDetailViewState,
+ private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
+) : VectorViewModel(initialState) {
+
+ @AssistedFactory
+ interface Factory : MavericksAssistedViewModelFactory {
+ override fun create(initialState: NewHomeDetailViewState): NewHomeDetailViewModel
+ }
+
+ companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
+
+ init {
+ observeSpacesNotificationCount()
+ }
+
+ private fun observeSpacesNotificationCount() {
+ getNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter)
+ .onEach { setState { copy(spacesNotificationCount = it) } }
+ .launchIn(viewModelScope)
+ }
+
+ override fun handle(action: EmptyAction) {
+ // do nothing
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
new file mode 100644
index 0000000000..20ad9be4b4
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home
+
+import com.airbnb.mvrx.MavericksState
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+
+data class NewHomeDetailViewState(
+ val spacesNotificationCount: RoomAggregateNotificationCount = RoomAggregateNotificationCount(notificationCount = 0, highlightCount = 0),
+) : MavericksState
From c36869cd03c14d00dfc8c025ee63606193545c33 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Tue, 21 Feb 2023 17:57:23 +0100
Subject: [PATCH 04/14] Adding knowledge of pending space invites
---
.../features/home/NewHomeDetailFragment.kt | 22 ++++++++++++++-----
.../features/home/NewHomeDetailViewState.kt | 1 +
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
index ff995311e6..51a217c526 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
@@ -185,7 +185,7 @@ class NewHomeDetailFragment :
}
newHomeDetailViewModel.onEach { viewState ->
- refreshUnreadCounterBadge(viewState.spacesNotificationCount)
+ refreshUnreadCounterBadge(viewState.spacesNotificationCount, viewState.hasPendingSpaceInvites)
}
}
@@ -386,11 +386,21 @@ class NewHomeDetailFragment :
}
}
- private fun refreshUnreadCounterBadge(roomAggregateNotificationCount: RoomAggregateNotificationCount) {
- val badgeState = UnreadCounterBadgeView.State.Count(
- count = roomAggregateNotificationCount.notificationCount,
- highlighted = roomAggregateNotificationCount.isHighlight,
- )
+ private fun refreshUnreadCounterBadge(
+ spacesNotificationCount: RoomAggregateNotificationCount,
+ hasPendingSpaceInvites: Boolean,
+ ) {
+ val badgeState = if (hasPendingSpaceInvites && spacesNotificationCount.notificationCount == 0) {
+ UnreadCounterBadgeView.State.Text(
+ text = "!",
+ highlighted = true,
+ )
+ } else {
+ UnreadCounterBadgeView.State.Count(
+ count = spacesNotificationCount.notificationCount,
+ highlighted = spacesNotificationCount.isHighlight,
+ )
+ }
views.spacesUnreadCounterBadge.render(badgeState)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
index 20ad9be4b4..1ff0b86511 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
@@ -21,4 +21,5 @@ import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotification
data class NewHomeDetailViewState(
val spacesNotificationCount: RoomAggregateNotificationCount = RoomAggregateNotificationCount(notificationCount = 0, highlightCount = 0),
+ val hasPendingSpaceInvites: Boolean = false,
) : MavericksState
From c74cdb9540cbf34b711dde2313ea1e043b174a18 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 10:44:55 +0100
Subject: [PATCH 05/14] Observe the spaces invites
---
.../features/home/NewHomeDetailViewModel.kt | 19 +++++++++-
.../app/features/spaces/GetSpacesUseCase.kt | 37 +++++++++++++++++++
.../app/features/spaces/SpaceListViewModel.kt | 8 ++--
3 files changed, 57 insertions(+), 7 deletions(-)
create mode 100644 vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
index 6f3ba79cf8..7f68accd90 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
@@ -25,16 +25,20 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
-import im.vector.app.features.roomprofile.polls.RoomPollsViewModel
-import im.vector.app.features.roomprofile.polls.RoomPollsViewState
+import im.vector.app.features.spaces.GetSpacesUseCase
import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
+// TODO add unit tests
class NewHomeDetailViewModel @AssistedInject constructor(
@Assisted initialState: NewHomeDetailViewState,
private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
+ private val getSpacesUseCase: GetSpacesUseCase,
) : VectorViewModel(initialState) {
@AssistedFactory
@@ -46,6 +50,7 @@ class NewHomeDetailViewModel @AssistedInject constructor(
init {
observeSpacesNotificationCount()
+ observeSpacesInvite()
}
private fun observeSpacesNotificationCount() {
@@ -54,6 +59,16 @@ class NewHomeDetailViewModel @AssistedInject constructor(
.launchIn(viewModelScope)
}
+ private fun observeSpacesInvite() {
+ val params = spaceSummaryQueryParams {
+ memberships = listOf(Membership.INVITE)
+ displayName = QueryStringValue.IsNotEmpty
+ }
+ getSpacesUseCase.execute(params)
+ .onEach { setState { copy(hasPendingSpaceInvites = it.isNotEmpty()) } }
+ .launchIn(viewModelScope)
+ }
+
override fun handle(action: EmptyAction) {
// do nothing
}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
new file mode 100644
index 0000000000..d3f462f9f9
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.spaces
+
+import im.vector.app.core.di.ActiveSessionHolder
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
+import org.matrix.android.sdk.flow.flow
+import javax.inject.Inject
+
+// TODO add unit tests
+class GetSpacesUseCase @Inject constructor(
+ private val activeSessionHolder: ActiveSessionHolder,
+) {
+
+ fun execute(params: SpaceSummaryQueryParams): Flow> {
+ val session = activeSessionHolder.getSafeActiveSession()
+
+ return session?.flow()?.liveSpaceSummaries(params) ?: emptyFlow()
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
index e5ebce0c11..b2776e5f87 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
@@ -29,7 +29,6 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.plan.Interaction
-import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
@@ -53,16 +52,15 @@ import org.matrix.android.sdk.api.session.space.SpaceOrderUtils
import org.matrix.android.sdk.api.session.space.model.SpaceOrderContent
import org.matrix.android.sdk.api.session.space.model.TopLevelSpaceComparator
import org.matrix.android.sdk.api.util.toMatrixItem
-import org.matrix.android.sdk.flow.flow
class SpaceListViewModel @AssistedInject constructor(
@Assisted initialState: SpaceListViewState,
private val spaceStateHandler: SpaceStateHandler,
private val session: Session,
private val vectorPreferences: VectorPreferences,
- private val autoAcceptInvites: AutoAcceptInvites,
private val analyticsTracker: AnalyticsTracker,
- private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
+ getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
+ private val getSpacesUseCase: GetSpacesUseCase,
) : VectorViewModel(initialState) {
@AssistedFactory
@@ -238,7 +236,7 @@ class SpaceListViewModel @AssistedInject constructor(
}
combine(
- session.flow().liveSpaceSummaries(params),
+ getSpacesUseCase.execute(params),
session.accountDataService()
.getLiveRoomAccountDataEvents(setOf(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER))
.asFlow()
From a509da54e80014b385f5b8840c4964774947d4ad Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 11:58:26 +0100
Subject: [PATCH 06/14] Adding unit tests for GetSpacesUseCase
---
.../app/features/spaces/GetSpacesUseCase.kt | 1 -
.../features/spaces/GetSpacesUseCaseTest.kt | 104 ++++++++++++++++++
.../im/vector/app/test/fakes/FakeSession.kt | 2 +
.../vector/app/test/fakes/FakeSpaceService.kt | 37 +++++++
4 files changed, 143 insertions(+), 1 deletion(-)
create mode 100644 vector/src/test/java/im/vector/app/features/spaces/GetSpacesUseCaseTest.kt
create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeSpaceService.kt
diff --git a/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
index d3f462f9f9..048e4b01bd 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/GetSpacesUseCase.kt
@@ -24,7 +24,6 @@ import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
import org.matrix.android.sdk.flow.flow
import javax.inject.Inject
-// TODO add unit tests
class GetSpacesUseCase @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
) {
diff --git a/vector/src/test/java/im/vector/app/features/spaces/GetSpacesUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/spaces/GetSpacesUseCaseTest.kt
new file mode 100644
index 0000000000..2e8d50ff3f
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/spaces/GetSpacesUseCaseTest.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.spaces
+
+import im.vector.app.test.fakes.FakeActiveSessionHolder
+import im.vector.app.test.fakes.FakeFlowLiveDataConversions
+import im.vector.app.test.fakes.givenAsFlow
+import im.vector.app.test.test
+import io.mockk.mockk
+import io.mockk.unmockkAll
+import io.mockk.verify
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
+
+internal class GetSpacesUseCaseTest {
+
+ private val fakeActiveSessionHolder = FakeActiveSessionHolder()
+ private val fakeFlowLiveDataConversions = FakeFlowLiveDataConversions()
+
+ private val getSpacesUseCase = GetSpacesUseCase(
+ activeSessionHolder = fakeActiveSessionHolder.instance,
+ )
+
+ @Before
+ fun setUp() {
+ fakeFlowLiveDataConversions.setup()
+ }
+
+ @After
+ fun tearDown() {
+ unmockkAll()
+ }
+
+ @Test
+ fun `given params when execute then the list of summaries is returned`() = runTest {
+ // Given
+ val queryParams = givenSpaceQueryParams()
+ val firstSummaries = listOf(mockk())
+ val nextSummaries = listOf(mockk())
+ fakeActiveSessionHolder.fakeSession
+ .fakeSpaceService
+ .givenGetSpaceSummariesReturns(firstSummaries)
+ fakeActiveSessionHolder.fakeSession
+ .fakeSpaceService
+ .givenGetSpaceSummariesLiveReturns(nextSummaries)
+ .givenAsFlow()
+
+ // When
+ val testObserver = getSpacesUseCase.execute(queryParams).test(this)
+ advanceUntilIdle()
+
+ // Then
+ testObserver
+ .assertValues(firstSummaries, nextSummaries)
+ .finish()
+ verify {
+ fakeActiveSessionHolder.fakeSession.fakeSpaceService.getSpaceSummaries(queryParams)
+ fakeActiveSessionHolder.fakeSession.fakeSpaceService.getSpaceSummariesLive(queryParams)
+ }
+ }
+
+ @Test
+ fun `given no active session when execute then empty flow is returned`() = runTest {
+ // Given
+ fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null)
+ val queryParams = givenSpaceQueryParams()
+
+ // When
+ val testObserver = getSpacesUseCase.execute(queryParams).test(this)
+ advanceUntilIdle()
+
+ // Then
+ testObserver
+ .assertNoValues()
+ .finish()
+ verify(inverse = true) {
+ fakeActiveSessionHolder.fakeSession.fakeSpaceService.getSpaceSummaries(queryParams)
+ fakeActiveSessionHolder.fakeSession.fakeSpaceService.getSpaceSummariesLive(queryParams)
+ }
+ }
+
+ private fun givenSpaceQueryParams(): SpaceSummaryQueryParams {
+ return mockk()
+ }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt
index 1b6d3e2729..ada23c159e 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSession.kt
@@ -46,6 +46,7 @@ class FakeSession(
val fakeUserService: FakeUserService = FakeUserService(),
private val fakeEventService: FakeEventService = FakeEventService(),
val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService(),
+ val fakeSpaceService: FakeSpaceService = FakeSpaceService(),
) : Session by mockk(relaxed = true) {
init {
@@ -66,6 +67,7 @@ class FakeSession(
override fun pushersService() = fakePushersService
override fun accountDataService() = fakeSessionAccountDataService
override fun userService() = fakeUserService
+ override fun spaceService() = fakeSpaceService
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
coEvery {
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceService.kt
new file mode 100644
index 0000000000..59c7d5524d
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeSpaceService.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.test.fakes
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import io.mockk.every
+import io.mockk.mockk
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.space.SpaceService
+
+class FakeSpaceService : SpaceService by mockk() {
+
+ fun givenGetSpaceSummariesLiveReturns(roomSummaries: List): LiveData> {
+ return MutableLiveData(roomSummaries).also {
+ every { getSpaceSummariesLive(any()) } returns it
+ }
+ }
+
+ fun givenGetSpaceSummariesReturns(roomSummaries: List) {
+ every { getSpaceSummaries(any()) } returns roomSummaries
+ }
+}
From e8c95551c1d69e30f6b760fa45ae3317be6bf462 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 14:19:21 +0100
Subject: [PATCH 07/14] Adding unit tests for
GetNotificationCountForSpacesUseCase
---
.../GetNotificationCountForSpacesUseCase.kt | 3 +-
...etNotificationCountForSpacesUseCaseTest.kt | 174 ++++++++++++++++++
.../app/test/fakes/FakeAutoAcceptInvites.kt | 4 +
.../test/fakes/FakeFlowLiveDataConversions.kt | 7 +-
.../vector/app/test/fakes/FakeRoomService.kt | 18 ++
5 files changed, 202 insertions(+), 4 deletions(-)
create mode 100644 vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
diff --git a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
index 5f79619c92..031015757d 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
@@ -32,7 +32,6 @@ import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
import javax.inject.Inject
-// TODO add unit tests
class GetNotificationCountForSpacesUseCase @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
private val autoAcceptInvites: AutoAcceptInvites,
@@ -64,7 +63,7 @@ class GetNotificationCountForSpacesUseCase @Inject constructor(
highlightCount = totalCount.highlightCount + inviteCount,
)
}
- ?.flowOn(Dispatchers.Default)
+ ?.flowOn(session.coroutineDispatchers.main)
?: emptyFlow()
}
}
diff --git a/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
new file mode 100644
index 0000000000..2813b9d79f
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.spaces.notification
+
+import androidx.paging.PagedList
+import im.vector.app.test.fakes.FakeActiveSessionHolder
+import im.vector.app.test.fakes.FakeAutoAcceptInvites
+import im.vector.app.test.fakes.FakeFlowLiveDataConversions
+import im.vector.app.test.fakes.givenAsFlow
+import im.vector.app.test.test
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.mockkStatic
+import io.mockk.unmockkAll
+import io.mockk.verify
+import kotlinx.coroutines.flow.sample
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+
+internal class GetNotificationCountForSpacesUseCaseTest {
+
+ private val fakeActiveSessionHolder = FakeActiveSessionHolder()
+ private val fakeAutoAcceptInvites = FakeAutoAcceptInvites()
+ private val fakeFlowLiveDataConversions = FakeFlowLiveDataConversions()
+
+ private val getNotificationCountForSpacesUseCase = GetNotificationCountForSpacesUseCase(
+ activeSessionHolder = fakeActiveSessionHolder.instance,
+ autoAcceptInvites = fakeAutoAcceptInvites,
+ )
+
+ @Before
+ fun setUp() {
+ fakeFlowLiveDataConversions.setup()
+ mockkStatic("kotlinx.coroutines.flow.FlowKt")
+ }
+
+ @After
+ fun tearDown() {
+ unmockkAll()
+ }
+
+ @Test
+ fun `given space filter and hide invites when execute then correct notification count is returned`() = runTest {
+ // given
+ val spaceFilter = SpaceFilter.NoFilter
+ val pagedList = mockk>()
+ val pagedListFlow = fakeActiveSessionHolder.fakeSession
+ .fakeRoomService
+ .givenGetPagedRoomSummariesLiveReturns(pagedList)
+ .givenAsFlow()
+ every { pagedListFlow.sample(any()) } returns pagedListFlow
+ val expectedNotificationCount = RoomAggregateNotificationCount(
+ notificationCount = 1,
+ highlightCount = 0,
+ )
+ fakeActiveSessionHolder.fakeSession
+ .fakeRoomService
+ .givenGetNotificationCountForRoomsReturns(expectedNotificationCount)
+ fakeAutoAcceptInvites._hideInvites = true
+
+ // When
+ val testObserver = getNotificationCountForSpacesUseCase.execute(spaceFilter).test(this)
+ advanceUntilIdle()
+
+ // Then
+ testObserver
+ .assertValues(expectedNotificationCount)
+ .finish()
+ verify {
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getNotificationCountForRooms(
+ queryParams = match { it.memberships == listOf(Membership.JOIN) && it.spaceFilter == spaceFilter }
+ )
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getPagedRoomSummariesLive(
+ queryParams = match { it.memberships == listOf(Membership.JOIN) && it.spaceFilter == spaceFilter },
+ pagedListConfig = any(),
+ sortOrder = RoomSortOrder.NONE,
+ )
+ }
+ }
+
+ @Test
+ fun `given space filter and show invites when execute then correct notification count is returned`() = runTest {
+ // given
+ val spaceFilter = SpaceFilter.NoFilter
+ val pagedList = mockk>()
+ val pagedListFlow = fakeActiveSessionHolder.fakeSession
+ .fakeRoomService
+ .givenGetPagedRoomSummariesLiveReturns(pagedList)
+ .givenAsFlow()
+ every { pagedListFlow.sample(any()) } returns pagedListFlow
+ val notificationCount = RoomAggregateNotificationCount(
+ notificationCount = 1,
+ highlightCount = 0,
+ )
+ fakeActiveSessionHolder.fakeSession
+ .fakeRoomService
+ .givenGetNotificationCountForRoomsReturns(notificationCount)
+ val invitedRooms = listOf(mockk())
+ fakeActiveSessionHolder.fakeSession
+ .fakeRoomService
+ .givenGetRoomSummaries(invitedRooms)
+ fakeAutoAcceptInvites._hideInvites = false
+ val expectedNotificationCount = RoomAggregateNotificationCount(
+ notificationCount = notificationCount.notificationCount + invitedRooms.size,
+ highlightCount = notificationCount.highlightCount + invitedRooms.size,
+ )
+
+ // When
+ val testObserver = getNotificationCountForSpacesUseCase.execute(spaceFilter).test(this)
+ advanceUntilIdle()
+
+ // Then
+ testObserver
+ .assertValues(expectedNotificationCount)
+ .finish()
+ verify {
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getRoomSummaries(
+ queryParams = match { it.memberships == listOf(Membership.INVITE) }
+ )
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getNotificationCountForRooms(
+ queryParams = match { it.memberships == listOf(Membership.JOIN) && it.spaceFilter == spaceFilter }
+ )
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getPagedRoomSummariesLive(
+ queryParams = match { it.memberships == listOf(Membership.JOIN) && it.spaceFilter == spaceFilter },
+ pagedListConfig = any(),
+ sortOrder = RoomSortOrder.NONE,
+ )
+ }
+ }
+
+ @Test
+ fun `given no active session when execute then empty flow is returned`() = runTest {
+ // given
+ val spaceFilter = SpaceFilter.NoFilter
+ fakeActiveSessionHolder.givenGetSafeActiveSessionReturns(null)
+
+ // When
+ val testObserver = getNotificationCountForSpacesUseCase.execute(spaceFilter).test(this)
+
+ // Then
+ testObserver
+ .assertNoValues()
+ .finish()
+ verify(inverse = true) {
+ fakeActiveSessionHolder.fakeSession.fakeRoomService.getPagedRoomSummariesLive(
+ queryParams = any(),
+ pagedListConfig = any(),
+ sortOrder = any(),
+ )
+ }
+ }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
index 778c2f113d..d1160cedfd 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
@@ -21,7 +21,11 @@ import im.vector.app.features.invite.AutoAcceptInvites
class FakeAutoAcceptInvites : AutoAcceptInvites {
var _isEnabled: Boolean = false
+ var _hideInvites: Boolean = false
override val isEnabled: Boolean
get() = _isEnabled
+
+ override val hideInvites: Boolean
+ get() = _hideInvites
}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeFlowLiveDataConversions.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeFlowLiveDataConversions.kt
index 956a86f32e..cdbe828521 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeFlowLiveDataConversions.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeFlowLiveDataConversions.kt
@@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.asFlow
import io.mockk.every
import io.mockk.mockkStatic
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
class FakeFlowLiveDataConversions {
@@ -28,6 +29,8 @@ class FakeFlowLiveDataConversions {
}
}
-fun LiveData.givenAsFlow() {
- every { asFlow() } returns flowOf(value!!)
+fun LiveData.givenAsFlow(): Flow {
+ return flowOf(value!!).also {
+ every { asFlow() } returns it
+ }
}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt
index e957266383..63209222b2 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRoomService.kt
@@ -16,10 +16,14 @@
package im.vector.app.test.fakes
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.paging.PagedList
import io.mockk.every
import io.mockk.mockk
import org.matrix.android.sdk.api.session.room.RoomService
import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
class FakeRoomService(
private val fakeRoom: FakeRoom = FakeRoom()
@@ -34,4 +38,18 @@ class FakeRoomService(
fun set(roomSummary: RoomSummary?) {
every { getRoomSummary(any()) } returns roomSummary
}
+
+ fun givenGetPagedRoomSummariesLiveReturns(pagedList: PagedList): LiveData> {
+ return MutableLiveData(pagedList).also {
+ every { getPagedRoomSummariesLive(queryParams = any(), pagedListConfig = any(), sortOrder = any()) } returns it
+ }
+ }
+
+ fun givenGetNotificationCountForRoomsReturns(roomAggregateNotificationCount: RoomAggregateNotificationCount) {
+ every { getNotificationCountForRooms(queryParams = any()) } returns roomAggregateNotificationCount
+ }
+
+ fun givenGetRoomSummaries(roomSummaries: List) {
+ every { getRoomSummaries(any()) } returns roomSummaries
+ }
}
From b78da9824d7d3a9218b4b33e8ee56c47e09fbfa4 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 14:38:35 +0100
Subject: [PATCH 08/14] Adding unit tests for NewHomeDetailViewModel
---
.../features/home/NewHomeDetailViewModel.kt | 1 -
.../home/NewHomeDetailViewModelTest.kt | 80 +++++++++++++++++++
2 files changed, 80 insertions(+), 1 deletion(-)
create mode 100644 vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
index 7f68accd90..b26d010137 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
@@ -34,7 +34,6 @@ import org.matrix.android.sdk.api.query.SpaceFilter
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
-// TODO add unit tests
class NewHomeDetailViewModel @AssistedInject constructor(
@Assisted initialState: NewHomeDetailViewState,
private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
diff --git a/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
new file mode 100644
index 0000000000..23882bf7c4
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home
+
+import com.airbnb.mvrx.test.MavericksTestRule
+import im.vector.app.features.spaces.GetSpacesUseCase
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
+import im.vector.app.test.test
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import org.junit.Rule
+import org.junit.Test
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+
+internal class NewHomeDetailViewModelTest {
+
+ @get:Rule
+ val mavericksTestRule = MavericksTestRule(testDispatcher = UnconfinedTestDispatcher())
+
+ private val initialState = NewHomeDetailViewState()
+ private val fakeGetNotificationCountForSpacesUseCase = mockk()
+ private val fakeGetSpacesUseCase = mockk()
+
+ private fun createViewModel(): NewHomeDetailViewModel {
+ return NewHomeDetailViewModel(
+ initialState = initialState,
+ getNotificationCountForSpacesUseCase = fakeGetNotificationCountForSpacesUseCase,
+ getSpacesUseCase = fakeGetSpacesUseCase,
+ )
+ }
+
+ @Test
+ fun `given the viewModel is created then viewState is updated with space notifications count and pending space invites`() {
+ // Given
+ val spacesNotificationCount = RoomAggregateNotificationCount(
+ notificationCount = 1,
+ highlightCount = 1,
+ )
+ every { fakeGetNotificationCountForSpacesUseCase.execute(any()) } returns flowOf(spacesNotificationCount)
+ val spaceInvites = listOf(mockk())
+ every { fakeGetSpacesUseCase.execute(any()) } returns flowOf(spaceInvites)
+ val expectedViewState = initialState.copy(
+ spacesNotificationCount = spacesNotificationCount,
+ hasPendingSpaceInvites = true,
+ )
+
+ // When
+ val viewModel = createViewModel()
+ val viewModelTest = viewModel.test()
+
+ // Then
+ viewModelTest
+ .assertLatestState(expectedViewState)
+ .finish()
+ verify {
+ fakeGetNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter)
+ fakeGetSpacesUseCase.execute(match { it.memberships == listOf(Membership.INVITE) })
+ }
+ }
+}
From 18c7f0d894e1d5867e4eee7092c118e0526189e9 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 14:39:44 +0100
Subject: [PATCH 09/14] Remove unused import
---
.../spaces/notification/GetNotificationCountForSpacesUseCase.kt | 1 -
1 file changed, 1 deletion(-)
diff --git a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
index 031015757d..08d63e2653 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
@@ -19,7 +19,6 @@ package im.vector.app.features.spaces.notification
import androidx.lifecycle.asFlow
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.invite.AutoAcceptInvites
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOn
From 1b0265662dc4bffe7eae381f58e7392705b440c5 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 14:50:01 +0100
Subject: [PATCH 10/14] Adding changelog entry
---
changelog.d/8157.feature | 1 +
1 file changed, 1 insertion(+)
create mode 100644 changelog.d/8157.feature
diff --git a/changelog.d/8157.feature b/changelog.d/8157.feature
new file mode 100644
index 0000000000..3cab2b600b
--- /dev/null
+++ b/changelog.d/8157.feature
@@ -0,0 +1 @@
+Add aggregated unread indicator for spaces in the new layout
From af4ab418510bd9b8cd35ae2f92382b91d2d536de Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Wed, 22 Feb 2023 15:04:14 +0100
Subject: [PATCH 11/14] Highlight the badge when there is pending space invite
---
.../java/im/vector/app/features/home/NewHomeDetailFragment.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
index 51a217c526..a13487afc8 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
@@ -398,7 +398,7 @@ class NewHomeDetailFragment :
} else {
UnreadCounterBadgeView.State.Count(
count = spacesNotificationCount.notificationCount,
- highlighted = spacesNotificationCount.isHighlight,
+ highlighted = spacesNotificationCount.isHighlight || hasPendingSpaceInvites,
)
}
views.spacesUnreadCounterBadge.render(badgeState)
From f782a315929b46db9bac0de3b19b23bfb7c986c6 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Thu, 23 Feb 2023 10:15:34 +0100
Subject: [PATCH 12/14] Fix unit tests
---
.../GetNotificationCountForSpacesUseCaseTest.kt | 6 +++---
.../java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt | 4 ----
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
index 2813b9d79f..8d4bdb1b30 100644
--- a/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
+++ b/vector/src/test/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCaseTest.kt
@@ -62,7 +62,7 @@ internal class GetNotificationCountForSpacesUseCaseTest {
}
@Test
- fun `given space filter and hide invites when execute then correct notification count is returned`() = runTest {
+ fun `given space filter and auto accept invites when execute then correct notification count is returned`() = runTest {
// given
val spaceFilter = SpaceFilter.NoFilter
val pagedList = mockk>()
@@ -78,7 +78,7 @@ internal class GetNotificationCountForSpacesUseCaseTest {
fakeActiveSessionHolder.fakeSession
.fakeRoomService
.givenGetNotificationCountForRoomsReturns(expectedNotificationCount)
- fakeAutoAcceptInvites._hideInvites = true
+ fakeAutoAcceptInvites._isEnabled = true
// When
val testObserver = getNotificationCountForSpacesUseCase.execute(spaceFilter).test(this)
@@ -121,7 +121,7 @@ internal class GetNotificationCountForSpacesUseCaseTest {
fakeActiveSessionHolder.fakeSession
.fakeRoomService
.givenGetRoomSummaries(invitedRooms)
- fakeAutoAcceptInvites._hideInvites = false
+ fakeAutoAcceptInvites._isEnabled = false
val expectedNotificationCount = RoomAggregateNotificationCount(
notificationCount = notificationCount.notificationCount + invitedRooms.size,
highlightCount = notificationCount.highlightCount + invitedRooms.size,
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
index d1160cedfd..778c2f113d 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAutoAcceptInvites.kt
@@ -21,11 +21,7 @@ import im.vector.app.features.invite.AutoAcceptInvites
class FakeAutoAcceptInvites : AutoAcceptInvites {
var _isEnabled: Boolean = false
- var _hideInvites: Boolean = false
override val isEnabled: Boolean
get() = _isEnabled
-
- override val hideInvites: Boolean
- get() = _hideInvites
}
From 2bd0126523cca2b15ce7d89a9e18fd5888fdf6bc Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Thu, 23 Feb 2023 13:59:32 +0100
Subject: [PATCH 13/14] Extracting logic to compute the badge state into a
usecase
---
.../GetSpacesNotificationBadgeStateUseCase.kt | 67 ++++++++++++++
.../features/home/NewHomeDetailFragment.kt | 19 +---
.../features/home/NewHomeDetailViewModel.kt | 28 ++----
.../features/home/NewHomeDetailViewState.kt | 5 +-
...SpacesNotificationBadgeStateUseCaseTest.kt | 88 +++++++++++++++++++
.../home/NewHomeDetailViewModelTest.kt | 33 +++----
6 files changed, 174 insertions(+), 66 deletions(-)
create mode 100644 vector/src/main/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCase.kt
create mode 100644 vector/src/test/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCaseTest.kt
diff --git a/vector/src/main/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCase.kt b/vector/src/main/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCase.kt
new file mode 100644
index 0000000000..62d1501dab
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCase.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home
+
+import im.vector.app.features.home.room.list.UnreadCounterBadgeView
+import im.vector.app.features.spaces.GetSpacesUseCase
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+import javax.inject.Inject
+
+class GetSpacesNotificationBadgeStateUseCase @Inject constructor(
+ private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
+ private val getSpacesUseCase: GetSpacesUseCase,
+) {
+
+ fun execute(): Flow {
+ val params = spaceSummaryQueryParams {
+ memberships = listOf(Membership.INVITE)
+ displayName = QueryStringValue.IsNotEmpty
+ }
+ return combine(
+ getNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter),
+ getSpacesUseCase.execute(params),
+ ) { spacesNotificationCount, spaceInvites ->
+ computeSpacesNotificationCounterBadgeState(spacesNotificationCount, spaceInvites)
+ }
+ }
+
+ private fun computeSpacesNotificationCounterBadgeState(
+ spacesNotificationCount: RoomAggregateNotificationCount,
+ spaceInvites: List,
+ ): UnreadCounterBadgeView.State {
+ val hasPendingSpaceInvites = spaceInvites.isNotEmpty()
+ return if (hasPendingSpaceInvites && spacesNotificationCount.notificationCount == 0) {
+ UnreadCounterBadgeView.State.Text(
+ text = "!",
+ highlighted = true,
+ )
+ } else {
+ UnreadCounterBadgeView.State.Count(
+ count = spacesNotificationCount.notificationCount,
+ highlighted = spacesNotificationCount.isHighlight || hasPendingSpaceInvites,
+ )
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
index a13487afc8..ef855ff15b 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailFragment.kt
@@ -64,7 +64,6 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
import org.matrix.android.sdk.api.session.room.model.RoomSummary
-import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
import javax.inject.Inject
@AndroidEntryPoint
@@ -185,7 +184,7 @@ class NewHomeDetailFragment :
}
newHomeDetailViewModel.onEach { viewState ->
- refreshUnreadCounterBadge(viewState.spacesNotificationCount, viewState.hasPendingSpaceInvites)
+ refreshUnreadCounterBadge(viewState.spacesNotificationCounterBadgeState)
}
}
@@ -386,21 +385,7 @@ class NewHomeDetailFragment :
}
}
- private fun refreshUnreadCounterBadge(
- spacesNotificationCount: RoomAggregateNotificationCount,
- hasPendingSpaceInvites: Boolean,
- ) {
- val badgeState = if (hasPendingSpaceInvites && spacesNotificationCount.notificationCount == 0) {
- UnreadCounterBadgeView.State.Text(
- text = "!",
- highlighted = true,
- )
- } else {
- UnreadCounterBadgeView.State.Count(
- count = spacesNotificationCount.notificationCount,
- highlighted = spacesNotificationCount.isHighlight || hasPendingSpaceInvites,
- )
- }
+ private fun refreshUnreadCounterBadge(badgeState: UnreadCounterBadgeView.State) {
views.spacesUnreadCounterBadge.render(badgeState)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
index b26d010137..67b4645944 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewModel.kt
@@ -25,19 +25,12 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
-import im.vector.app.features.spaces.GetSpacesUseCase
-import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import org.matrix.android.sdk.api.query.QueryStringValue
-import org.matrix.android.sdk.api.query.SpaceFilter
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
class NewHomeDetailViewModel @AssistedInject constructor(
@Assisted initialState: NewHomeDetailViewState,
- private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
- private val getSpacesUseCase: GetSpacesUseCase,
+ private val getSpacesNotificationBadgeStateUseCase: GetSpacesNotificationBadgeStateUseCase,
) : VectorViewModel(initialState) {
@AssistedFactory
@@ -48,23 +41,12 @@ class NewHomeDetailViewModel @AssistedInject constructor(
companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
init {
- observeSpacesNotificationCount()
- observeSpacesInvite()
+ observeSpacesNotificationBadgeState()
}
- private fun observeSpacesNotificationCount() {
- getNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter)
- .onEach { setState { copy(spacesNotificationCount = it) } }
- .launchIn(viewModelScope)
- }
-
- private fun observeSpacesInvite() {
- val params = spaceSummaryQueryParams {
- memberships = listOf(Membership.INVITE)
- displayName = QueryStringValue.IsNotEmpty
- }
- getSpacesUseCase.execute(params)
- .onEach { setState { copy(hasPendingSpaceInvites = it.isNotEmpty()) } }
+ private fun observeSpacesNotificationBadgeState() {
+ getSpacesNotificationBadgeStateUseCase.execute()
+ .onEach { badgeState -> setState { copy(spacesNotificationCounterBadgeState = badgeState) } }
.launchIn(viewModelScope)
}
diff --git a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
index 1ff0b86511..7e368fb2d1 100644
--- a/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/home/NewHomeDetailViewState.kt
@@ -17,9 +17,8 @@
package im.vector.app.features.home
import com.airbnb.mvrx.MavericksState
-import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+import im.vector.app.features.home.room.list.UnreadCounterBadgeView
data class NewHomeDetailViewState(
- val spacesNotificationCount: RoomAggregateNotificationCount = RoomAggregateNotificationCount(notificationCount = 0, highlightCount = 0),
- val hasPendingSpaceInvites: Boolean = false,
+ val spacesNotificationCounterBadgeState: UnreadCounterBadgeView.State = UnreadCounterBadgeView.State.Count(count = 0, highlighted = false),
) : MavericksState
diff --git a/vector/src/test/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCaseTest.kt
new file mode 100644
index 0000000000..4d7d0d98f4
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/home/GetSpacesNotificationBadgeStateUseCaseTest.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home
+
+import im.vector.app.features.home.room.list.UnreadCounterBadgeView
+import im.vector.app.features.spaces.GetSpacesUseCase
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
+import im.vector.app.test.test
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+
+internal class GetSpacesNotificationBadgeStateUseCaseTest {
+
+ private val fakeGetNotificationCountForSpacesUseCase = mockk()
+ private val fakeGetSpacesUseCase = mockk()
+
+ private val getSpacesNotificationBadgeStateUseCase = GetSpacesNotificationBadgeStateUseCase(
+ getNotificationCountForSpacesUseCase = fakeGetNotificationCountForSpacesUseCase,
+ getSpacesUseCase = fakeGetSpacesUseCase,
+ )
+
+ @Test
+ fun `given flow of spaces invite and notification count then flow of state is correct`() = runTest {
+ // Given
+ val noSpacesInvite = emptyList()
+ val existingSpaceInvite = listOf(mockk())
+ val noNotification = RoomAggregateNotificationCount(
+ notificationCount = 0,
+ highlightCount = 0,
+ )
+ val existingNotificationNotHighlighted = RoomAggregateNotificationCount(
+ notificationCount = 1,
+ highlightCount = 0,
+ )
+ val existingNotificationHighlighted = RoomAggregateNotificationCount(
+ notificationCount = 1,
+ highlightCount = 1,
+ )
+ every { fakeGetSpacesUseCase.execute(any()) } returns
+ flowOf(noSpacesInvite, existingSpaceInvite, existingSpaceInvite, noSpacesInvite, noSpacesInvite)
+ every { fakeGetNotificationCountForSpacesUseCase.execute(any()) } returns
+ flowOf(noNotification, noNotification, existingNotificationNotHighlighted, existingNotificationNotHighlighted, existingNotificationHighlighted)
+
+ // When
+ val testObserver = getSpacesNotificationBadgeStateUseCase.execute().test(this)
+ advanceUntilIdle()
+
+ // Then
+ val expectedState1 = UnreadCounterBadgeView.State.Count(count = 0, highlighted = false)
+ val expectedState2 = UnreadCounterBadgeView.State.Text(text = "!", highlighted = true)
+ val expectedState3 = UnreadCounterBadgeView.State.Count(count = 1, highlighted = true)
+ val expectedState4 = UnreadCounterBadgeView.State.Count(count = 1, highlighted = false)
+ val expectedState5 = UnreadCounterBadgeView.State.Count(count = 1, highlighted = true)
+ testObserver
+ .assertValues(expectedState1, expectedState2, expectedState3, expectedState4, expectedState5)
+ .finish()
+ verify {
+ fakeGetSpacesUseCase.execute(match {
+ it.memberships == listOf(Membership.INVITE) && it.displayName == QueryStringValue.IsNotEmpty
+ })
+ }
+ verify { fakeGetNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter) }
+ }
+}
diff --git a/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
index 23882bf7c4..a92c4be0d7 100644
--- a/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
+++ b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
@@ -17,8 +17,8 @@
package im.vector.app.features.home
import com.airbnb.mvrx.test.MavericksTestRule
+import im.vector.app.features.home.room.list.UnreadCounterBadgeView
import im.vector.app.features.spaces.GetSpacesUseCase
-import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
import im.vector.app.test.test
import io.mockk.every
import io.mockk.mockk
@@ -27,10 +27,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Rule
import org.junit.Test
-import org.matrix.android.sdk.api.query.SpaceFilter
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.model.RoomSummary
-import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
internal class NewHomeDetailViewModelTest {
@@ -38,43 +34,34 @@ internal class NewHomeDetailViewModelTest {
val mavericksTestRule = MavericksTestRule(testDispatcher = UnconfinedTestDispatcher())
private val initialState = NewHomeDetailViewState()
- private val fakeGetNotificationCountForSpacesUseCase = mockk()
- private val fakeGetSpacesUseCase = mockk()
+ private val fakeGetSpacesNotificationBadgeStateUseCase = mockk()
private fun createViewModel(): NewHomeDetailViewModel {
return NewHomeDetailViewModel(
initialState = initialState,
- getNotificationCountForSpacesUseCase = fakeGetNotificationCountForSpacesUseCase,
- getSpacesUseCase = fakeGetSpacesUseCase,
+ getSpacesNotificationBadgeStateUseCase = fakeGetSpacesNotificationBadgeStateUseCase,
)
}
@Test
- fun `given the viewModel is created then viewState is updated with space notifications count and pending space invites`() {
+ fun `given the viewModel is created then viewState is updated with space notifications badge state`() {
// Given
- val spacesNotificationCount = RoomAggregateNotificationCount(
- notificationCount = 1,
- highlightCount = 1,
- )
- every { fakeGetNotificationCountForSpacesUseCase.execute(any()) } returns flowOf(spacesNotificationCount)
- val spaceInvites = listOf(mockk())
- every { fakeGetSpacesUseCase.execute(any()) } returns flowOf(spaceInvites)
- val expectedViewState = initialState.copy(
- spacesNotificationCount = spacesNotificationCount,
- hasPendingSpaceInvites = true,
- )
+ val aBadgeState = UnreadCounterBadgeView.State.Count(count = 1, highlighted = false)
+ every { fakeGetSpacesNotificationBadgeStateUseCase.execute() } returns flowOf(aBadgeState)
// When
val viewModel = createViewModel()
val viewModelTest = viewModel.test()
// Then
+ val expectedViewState = initialState.copy(
+ spacesNotificationCounterBadgeState = aBadgeState,
+ )
viewModelTest
.assertLatestState(expectedViewState)
.finish()
verify {
- fakeGetNotificationCountForSpacesUseCase.execute(SpaceFilter.NoFilter)
- fakeGetSpacesUseCase.execute(match { it.memberships == listOf(Membership.INVITE) })
+ fakeGetSpacesNotificationBadgeStateUseCase.execute()
}
}
}
From 53d03335abcf92853c636535a5e4bbc2d915f5f0 Mon Sep 17 00:00:00 2001
From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com>
Date: Thu, 23 Feb 2023 14:18:21 +0100
Subject: [PATCH 14/14] Remove unused import
---
.../im/vector/app/features/home/NewHomeDetailViewModelTest.kt | 1 -
1 file changed, 1 deletion(-)
diff --git a/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
index a92c4be0d7..39adc0a811 100644
--- a/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
+++ b/vector/src/test/java/im/vector/app/features/home/NewHomeDetailViewModelTest.kt
@@ -18,7 +18,6 @@ package im.vector.app.features.home
import com.airbnb.mvrx.test.MavericksTestRule
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
-import im.vector.app.features.spaces.GetSpacesUseCase
import im.vector.app.test.test
import io.mockk.every
import io.mockk.mockk