diff --git a/changelog.d/6598.misc b/changelog.d/6598.misc new file mode 100644 index 0000000000..db65a30bdc --- /dev/null +++ b/changelog.d/6598.misc @@ -0,0 +1 @@ +Refactors SpaceStateHandler (previously AppStateHandler) and adds unit tests for it diff --git a/vector/src/main/java/im/vector/app/SpaceStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt new file mode 100644 index 0000000000..174b8ab3cd --- /dev/null +++ b/vector/src/main/java/im/vector/app/SpaceStateHandler.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 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 + +import androidx.lifecycle.DefaultLifecycleObserver +import arrow.core.Option +import kotlinx.coroutines.flow.Flow +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.room.model.RoomSummary + +/** + * Gets info about the current space the user has navigated to, any space backstack they may have + * and handles switching to different spaces + */ +interface SpaceStateHandler : DefaultLifecycleObserver { + + /** + * Gets the current space the current user has navigated to + * + * @return null if the user is not in + */ + fun getCurrentSpace(): RoomSummary? + + /** + * Sets the new space the current user is navigating to + * + * @param spaceId the id of the space being navigated to + * @param session the current active session + * @param persistNow if true, the current space will immediately be persisted in shared prefs + * @param isForwardNavigation whether this navigation is a forward action to properly handle backstack + */ + fun setCurrentSpace( + spaceId: String?, + session: Session? = null, + persistNow: Boolean = false, + isForwardNavigation: Boolean = true, + ) + + /** + * Gets the current backstack of spaces (via their id) + * + * null may be an entry in the ArrayDeque to indicate the root space (All Chats) + */ + fun getSpaceBackstack(): ArrayDeque + + /** + * Gets a flow of the selected space for clients to react immediately to space changes + */ + fun getSelectedSpaceFlow(): Flow> + + /** + * Gets the id of the active space, or null if there is none + */ + fun getSafeActiveSpaceId(): String? +} diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt similarity index 76% rename from vector/src/main/java/im/vector/app/AppStateHandler.kt rename to vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt index e18b576637..c6a4b2c5f0 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/SpaceStateHandlerImpl.kt @@ -16,7 +16,6 @@ package im.vector.app -import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import arrow.core.Option import im.vector.app.core.di.ActiveSessionHolder @@ -46,54 +45,60 @@ import javax.inject.Singleton /** * This class handles the global app state. - * It requires to be added to ProcessLifecycleOwner.get().lifecycle + * It is required that this class is added as an observer to ProcessLifecycleOwner.get().lifecycle in [VectorApplication] */ -// TODO Keep this class for now, will maybe be used fro Space @Singleton -class AppStateHandler @Inject constructor( +class SpaceStateHandlerImpl @Inject constructor( private val sessionDataSource: ActiveSessionDataSource, private val uiStateRepository: UiStateRepository, private val activeSessionHolder: ActiveSessionHolder, private val analyticsTracker: AnalyticsTracker -) : DefaultLifecycleObserver { +) : SpaceStateHandler { private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) - - val selectedSpaceFlow = selectedSpaceDataSource.stream() - + private val selectedSpaceFlow = selectedSpaceDataSource.stream() private val spaceBackstack = ArrayDeque() - fun getCurrentSpace(): RoomSummary? { + override fun getCurrentSpace(): RoomSummary? { return selectedSpaceDataSource.currentValue?.orNull()?.let { spaceSummary -> activeSessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(spaceSummary.roomId) } } - fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false, isForwardNavigation: Boolean = true) { + override fun setCurrentSpace( + spaceId: String?, + session: Session?, + persistNow: Boolean, + isForwardNavigation: Boolean, + ) { + val activeSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return val currentSpace = selectedSpaceDataSource.currentValue?.orNull() - val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - if (currentSpace != null && spaceId == currentSpace.roomId) return - val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) } + val spaceSummary = spaceId?.let { activeSession.getRoomSummary(spaceId) } + val sameSpaceSelected = currentSpace != null && spaceId == currentSpace.roomId + + if (sameSpaceSelected) { + return + } if (isForwardNavigation) { spaceBackstack.addLast(currentSpace?.roomId) } if (persistNow) { - uiStateRepository.storeSelectedSpace(spaceSum?.roomId, uSession.sessionId) + uiStateRepository.storeSelectedSpace(spaceSummary?.roomId, activeSession.sessionId) } - if (spaceSum == null) { + if (spaceSummary == null) { selectedSpaceDataSource.post(Option.empty()) } else { - selectedSpaceDataSource.post(Option.just(spaceSum)) + selectedSpaceDataSource.post(Option.just(spaceSummary)) } if (spaceId != null) { - uSession.coroutineScope.launch(Dispatchers.IO) { + activeSession.coroutineScope.launch(Dispatchers.IO) { tryOrNull { - uSession.getRoom(spaceId)?.membershipService()?.loadRoomMembersIfNeeded() + activeSession.getRoom(spaceId)?.membershipService()?.loadRoomMembersIfNeeded() } } } @@ -122,9 +127,11 @@ class AppStateHandler @Inject constructor( }.launchIn(session.coroutineScope) } - fun getSpaceBackstack() = spaceBackstack + override fun getSpaceBackstack() = spaceBackstack - fun safeActiveSpaceId(): String? { + override fun getSelectedSpaceFlow() = selectedSpaceFlow + + override fun getSafeActiveSpaceId(): String? { return selectedSpaceDataSource.currentValue?.orNull()?.roomId } diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index 24d9770604..d3dfbf8c4f 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -88,7 +88,7 @@ class VectorApplication : @Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var versionProvider: VersionProvider @Inject lateinit var notificationUtils: NotificationUtils - @Inject lateinit var appStateHandler: AppStateHandler + @Inject lateinit var spaceStateHandler: SpaceStateHandler @Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var pinLocker: PinLocker @Inject lateinit var callManager: WebRtcCallManager @@ -177,7 +177,7 @@ class VectorApplication : fcmHelper.onEnterBackground(activeSessionHolder) } }) - ProcessLifecycleOwner.get().lifecycle.addObserver(appStateHandler) + ProcessLifecycleOwner.get().lifecycle.addObserver(spaceStateHandler) ProcessLifecycleOwner.get().lifecycle.addObserver(pinLocker) ProcessLifecycleOwner.get().lifecycle.addObserver(callManager) // This should be done as early as possible diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 602fd73034..c969df74e4 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -31,6 +31,8 @@ import dagger.hilt.components.SingletonComponent import im.vector.app.BuildConfig import im.vector.app.EmojiCompatWrapper import im.vector.app.EmojiSpanify +import im.vector.app.SpaceStateHandler +import im.vector.app.SpaceStateHandlerImpl import im.vector.app.config.analyticsConfig import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.error.DefaultErrorFormatter @@ -108,6 +110,9 @@ abstract class VectorBindModule { @Binds abstract fun bindSystemSettingsProvide(provider: AndroidSystemSettingsProvider): SystemSettingsProvider + + @Binds + abstract fun bindSpaceStateHandler(spaceStateHandlerImpl: SpaceStateHandlerImpl): SpaceStateHandler } @InstallIn(SingletonComponent::class) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 2d5f94a749..389b4b7b27 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -35,8 +35,8 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.viewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.registerStartForActivityResult @@ -130,7 +130,7 @@ class HomeActivity : @Inject lateinit var permalinkHandler: PermalinkHandler @Inject lateinit var avatarRenderer: AvatarRenderer @Inject lateinit var initSyncStepFormatter: InitSyncStepFormatter - @Inject lateinit var appStateHandler: AppStateHandler + @Inject lateinit var spaceStateHandler: SpaceStateHandler @Inject lateinit var unifiedPushHelper: UnifiedPushHelper @Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var nightlyProxy: NightlyProxy diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index f7fd268082..d96b44b705 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -28,8 +28,8 @@ import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.badge.BadgeDrawable -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed @@ -68,7 +68,7 @@ class HomeDetailFragment @Inject constructor( private val alertManager: PopupAlertManager, private val callManager: WebRtcCallManager, private val vectorPreferences: VectorPreferences, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val vectorFeatures: VectorFeatures, ) : VectorBaseFragment(), KeysBackupBanner.Delegate, @@ -186,13 +186,13 @@ class HomeDetailFragment @Inject constructor( } private fun navigateBack() { - val previousSpaceId = appStateHandler.getSpaceBackstack().removeLastOrNull() - val parentSpaceId = appStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() + val previousSpaceId = spaceStateHandler.getSpaceBackstack().removeLastOrNull() + val parentSpaceId = spaceStateHandler.getCurrentSpace()?.flattenParentIds?.lastOrNull() setCurrentSpace(previousSpaceId ?: parentSpaceId) } private fun setCurrentSpace(spaceId: String?) { - appStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) + spaceStateHandler.setCurrentSpace(spaceId, isForwardNavigation = false) sharedActionViewModel.post(HomeActivitySharedAction.OnCloseSpace) } @@ -215,7 +215,7 @@ class HomeDetailFragment @Inject constructor( } private fun refreshSpaceState() { - appStateHandler.getCurrentSpace()?.let { + spaceStateHandler.getCurrentSpace()?.let { onSpaceChange(it) } } @@ -473,7 +473,7 @@ class HomeDetailFragment @Inject constructor( return this } - override fun onBackPressed(toolbarButton: Boolean) = if (appStateHandler.getCurrentSpace() != null) { + override fun onBackPressed(toolbarButton: Boolean) = if (spaceStateHandler.getCurrentSpace() != null) { navigateBack() true } else { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 4be30f753b..b010a9d577 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -22,7 +22,7 @@ import com.airbnb.mvrx.ViewModelContext import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.singletonEntryPoint @@ -68,7 +68,7 @@ class HomeDetailViewModel @AssistedInject constructor( private val vectorDataStore: VectorDataStore, private val callManager: WebRtcCallManager, private val directRoomHelper: DirectRoomHelper, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val autoAcceptInvites: AutoAcceptInvites, private val vectorOverrides: VectorOverrides ) : VectorViewModel(initialState), @@ -206,7 +206,7 @@ class HomeDetailViewModel @AssistedInject constructor( } private fun observeRoomGroupingMethod() { - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .setOnEach { copy( selectedSpace = it.orNull() @@ -215,7 +215,7 @@ class HomeDetailViewModel @AssistedInject constructor( } private fun observeRoomSummaries() { - appStateHandler.selectedSpaceFlow.distinctUntilChanged().flatMapLatest { + spaceStateHandler.getSelectedSpaceFlow().distinctUntilChanged().flatMapLatest { // we use it as a trigger to all changes in room, but do not really load // the actual models session.roomService().getPagedRoomSummariesLive( @@ -227,7 +227,7 @@ class HomeDetailViewModel @AssistedInject constructor( } .throttleFirst(300) .onEach { - val activeSpaceRoomId = appStateHandler.getCurrentSpace()?.roomId + val activeSpaceRoomId = spaceStateHandler.getCurrentSpace()?.roomId var dmInvites = 0 var roomsInvite = 0 if (autoAcceptInvites.showInvites()) { diff --git a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt index 5f4782123c..25781e68f0 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnreadMessagesSharedViewModel.kt @@ -22,7 +22,7 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.EmptyAction @@ -58,7 +58,7 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor( @Assisted initialState: UnreadMessagesState, session: Session, private val vectorPreferences: VectorPreferences, - appStateHandler: AppStateHandler, + spaceStateHandler: SpaceStateHandler, private val autoAcceptInvites: AutoAcceptInvites ) : VectorViewModel(initialState) { @@ -109,8 +109,8 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor( } combine( - appStateHandler.selectedSpaceFlow.distinctUntilChanged(), - appStateHandler.selectedSpaceFlow.flatMapLatest { + spaceStateHandler.getSelectedSpaceFlow().distinctUntilChanged(), + spaceStateHandler.getSelectedSpaceFlow().flatMapLatest { roomService.getPagedRoomSummariesLive( roomSummaryQueryParams { this.memberships = Membership.activeMemberships() @@ -162,10 +162,10 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor( CountInfo( homeCount = counts, otherCount = RoomAggregateNotificationCount( - notificationCount = rootCounts.fold(0, { acc, rs -> acc + rs.notificationCount }) + + notificationCount = rootCounts.fold(0) { acc, rs -> acc + rs.notificationCount } + (counts.notificationCount.takeIf { selectedSpace != null } ?: 0) + spaceInviteCount, - highlightCount = rootCounts.fold(0, { acc, rs -> acc + rs.highlightCount }) + + highlightCount = rootCounts.fold(0) { acc, rs -> acc + rs.highlightCount } + (counts.highlightCount.takeIf { selectedSpace != null } ?: 0) + spaceInviteCount ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 69af183885..848bd3aed4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -27,8 +27,8 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.mvrx.runCatchingToAsync @@ -138,7 +138,7 @@ class TimelineViewModel @AssistedInject constructor( private val stopLiveLocationShareUseCase: StopLiveLocationShareUseCase, private val redactLiveLocationShareEventUseCase: RedactLiveLocationShareEventUseCase, timelineFactory: TimelineFactory, - appStateHandler: AppStateHandler, + spaceStateHandler: SpaceStateHandler, ) : VectorViewModel(initialState), Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener, LocationSharingServiceConnection.Callback { @@ -220,16 +220,16 @@ class TimelineViewModel @AssistedInject constructor( if (initialState.switchToParentSpace) { // We are coming from a notification, try to switch to the most relevant space // so that when hitting back the room will appear in the list - appStateHandler.getCurrentSpace().let { currentSpace -> + spaceStateHandler.getCurrentSpace().let { currentSpace -> val currentRoomSummary = room.roomSummary() ?: return@let // nothing we are good if ((currentSpace == null && !vectorPreferences.prefSpacesShowAllRoomInHome()) || (currentSpace != null && !currentRoomSummary.flattenParentIds.contains(currentSpace.roomId))) { // take first one or switch to home - appStateHandler.setCurrentSpace( + spaceStateHandler.setCurrentSpace( currentRoomSummary .flattenParentIds.firstOrNull { it.isNotBlank() }, - // force persist, because if not on resume the AppStateHandler will resume + // force persist, because if not on resume the SpaceStateHandler will resume // the current space from what was persisted on enter background persistNow = true ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt index b2187fb365..236cf3fb69 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilder.kt @@ -23,8 +23,8 @@ import androidx.lifecycle.asFlow import androidx.lifecycle.liveData import androidx.paging.PagedList import com.airbnb.mvrx.Async -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.invite.AutoAcceptInvites @@ -59,7 +59,7 @@ import timber.log.Timber class RoomListSectionBuilder( private val session: Session, private val stringProvider: StringProvider, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val viewModelScope: CoroutineScope, private val autoAcceptInvites: AutoAcceptInvites, private val onUpdatable: (UpdatableLivePageResult) -> Unit, @@ -95,7 +95,7 @@ class RoomListSectionBuilder( } } - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .onEach { selectedSpaceOption -> val selectedSpace = selectedSpaceOption.orNull() @@ -150,7 +150,7 @@ class RoomListSectionBuilder( ) { it.memberships = listOf(Membership.JOIN) it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, false) + it.roomTagQueryFilter = RoomTagQueryFilter(isFavorite = false, isLowPriority = false, isServerNotice = false) } addSection( @@ -187,7 +187,7 @@ class RoomListSectionBuilder( // add suggested rooms val suggestedRoomsFlow = // MutableLiveData>() - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .flatMapLatest { selectedSpaceOption -> val selectedSpace = selectedSpaceOption.orNull() @@ -271,7 +271,7 @@ class RoomListSectionBuilder( ) { it.memberships = listOf(Membership.JOIN) it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, false, null) + it.roomTagQueryFilter = RoomTagQueryFilter(isFavorite = false, isLowPriority = false, isServerNotice = null) } addSection( @@ -283,7 +283,7 @@ class RoomListSectionBuilder( ) { it.memberships = listOf(Membership.JOIN) it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM - it.roomTagQueryFilter = RoomTagQueryFilter(false, true, null) + it.roomTagQueryFilter = RoomTagQueryFilter(isFavorite = false, isLowPriority = true, isServerNotice = null) } } @@ -360,7 +360,7 @@ class RoomListSectionBuilder( query: (RoomSummaryQueryParams.Builder) -> Unit ) { withQueryParams(query) { roomQueryParams -> - val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, spaceStateHandler.getSafeActiveSpaceId()) val liveQueryParams = MutableStateFlow(updatedQueryParams) val itemCountFlow = liveQueryParams .flatMapLatest { @@ -371,7 +371,7 @@ class RoomListSectionBuilder( val name = stringProvider.getString(nameRes) val filteredPagedRoomSummariesLive = session.roomService().getFilteredPagedRoomSummariesLive( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), + roomQueryParams.process(spaceFilterStrategy, spaceStateHandler.getSafeActiveSpaceId()), pagedListConfig ) when (spaceFilterStrategy) { @@ -418,7 +418,7 @@ class RoomListSectionBuilder( RoomAggregateNotificationCount(it.size, it.size) } else { session.roomService().getNotificationCountForRooms( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + roomQueryParams.process(spaceFilterStrategy, spaceStateHandler.getSafeActiveSpaceId()) ) } ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index 77f7c148d9..4b76daf502 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -25,7 +25,7 @@ import com.airbnb.mvrx.Success import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -60,7 +60,7 @@ class RoomListViewModel @AssistedInject constructor( @Assisted initialState: RoomListViewState, private val session: Session, stringProvider: StringProvider, - appStateHandler: AppStateHandler, + spaceStateHandler: SpaceStateHandler, vectorPreferences: VectorPreferences, autoAcceptInvites: AutoAcceptInvites, private val analyticsTracker: AnalyticsTracker @@ -100,7 +100,7 @@ class RoomListViewModel @AssistedInject constructor( observeMembershipChanges() observeLocalRooms() - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .execute { copy( @@ -146,17 +146,17 @@ class RoomListViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() private val roomListSectionBuilder = RoomListSectionBuilder( - session, - stringProvider, - appStateHandler, - viewModelScope, - autoAcceptInvites, - { - updatableQuery = it - }, - suggestedRoomJoiningState, - !vectorPreferences.prefSpacesShowAllRoomInHome() - ) + session, + stringProvider, + spaceStateHandler, + viewModelScope, + autoAcceptInvites, + { + updatableQuery = it + }, + suggestedRoomJoiningState, + !vectorPreferences.prefSpacesShowAllRoomInHome() + ) val sections: List by lazy { roomListSectionBuilder.buildSections(initialState.displayMode) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt index 7b257b1d1c..b95ec50ab0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt @@ -22,7 +22,7 @@ import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.StateView @@ -50,7 +50,7 @@ import org.matrix.android.sdk.api.session.room.state.isPublic class HomeRoomListViewModel @AssistedInject constructor( @Assisted initialState: HomeRoomListViewState, private val session: Session, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val vectorPreferences: VectorPreferences, ) : VectorViewModel(initialState) { @@ -99,10 +99,10 @@ class HomeRoomListViewModel @AssistedInject constructor( pagedListConfig ) - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .onStart { - emit(appStateHandler.getCurrentSpace().toOption()) + emit(spaceStateHandler.getCurrentSpace().toOption()) } .onEach { selectedSpaceOption -> val selectedSpace = selectedSpaceOption.orNull() diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 2a1095fb7a..67bc9a78e7 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -31,8 +31,8 @@ import androidx.core.app.TaskStackBuilder import androidx.core.util.Pair import androidx.core.view.ViewCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.AppStateHandler import im.vector.app.R +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.fatalError import im.vector.app.features.VectorFeatures @@ -120,7 +120,7 @@ class DefaultNavigator @Inject constructor( private val sessionHolder: ActiveSessionHolder, private val vectorPreferences: VectorPreferences, private val widgetArgsBuilder: WidgetArgsBuilder, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider, private val features: VectorFeatures, private val analyticsTracker: AnalyticsTracker @@ -167,7 +167,7 @@ class DefaultNavigator @Inject constructor( analyticsTracker.capture( sessionHolder.getActiveSession().getRoomSummary(roomId).toAnalyticsViewRoom( trigger = trigger, - selectedSpace = appStateHandler.getCurrentSpace() + selectedSpace = spaceStateHandler.getCurrentSpace() ) ) } @@ -182,7 +182,7 @@ class DefaultNavigator @Inject constructor( fatalError("Trying to open an unknown space $spaceId", vectorPreferences.failFast()) return } - appStateHandler.setCurrentSpace(spaceId) + spaceStateHandler.setCurrentSpace(spaceId) when (postSwitchSpaceAction) { Navigator.PostSwitchSpaceAction.None -> { // go back to home if we are showing room details? @@ -318,7 +318,7 @@ class DefaultNavigator @Inject constructor( } override fun openRoomDirectory(context: Context, initialFilter: String) { - when (val currentSpace = appStateHandler.getCurrentSpace()) { + when (val currentSpace = spaceStateHandler.getCurrentSpace()) { null -> RoomDirectoryActivity.getIntent(context, initialFilter) else -> SpaceExploreActivity.newIntent(context, currentSpace.roomId) }.start(context) @@ -330,14 +330,14 @@ class DefaultNavigator @Inject constructor( } override fun openCreateDirectRoom(context: Context) { - when (val currentSpace = appStateHandler.getCurrentSpace()) { + when (val currentSpace = spaceStateHandler.getCurrentSpace()) { null -> CreateDirectRoomActivity.getIntent(context) else -> SpacePeopleActivity.newIntent(context, currentSpace.roomId) }.start(context) } override fun openInviteUsersToRoom(context: Context, roomId: String) { - when (val currentSpace = appStateHandler.getCurrentSpace()) { + when (val currentSpace = spaceStateHandler.getCurrentSpace()) { null -> InviteUsersToRoomActivity.getIntent(context, roomId).start(context) else -> showInviteToDialog(context, currentSpace, roomId) } diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt index e068d21b36..2616d808f2 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/createroom/CreateRoomViewModel.kt @@ -25,7 +25,7 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -58,7 +58,7 @@ class CreateRoomViewModel @AssistedInject constructor( @Assisted private val initialState: CreateRoomViewState, private val session: Session, private val rawService: RawService, - appStateHandler: AppStateHandler, + spaceStateHandler: SpaceStateHandler, private val analyticsTracker: AnalyticsTracker ) : VectorViewModel(initialState) { @@ -73,7 +73,7 @@ class CreateRoomViewModel @AssistedInject constructor( initHomeServerName() initAdminE2eByDefault() - val parentSpaceId = initialState.parentSpaceId ?: appStateHandler.safeActiveSpaceId() + val parentSpaceId = initialState.parentSpaceId ?: spaceStateHandler.getSafeActiveSpaceId() val restrictedSupport = session.homeServerCapabilitiesService().getHomeServerCapabilities() .isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED) 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 a104e9b170..eea11f9b1b 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 @@ -23,7 +23,7 @@ import com.airbnb.mvrx.Success import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel @@ -61,7 +61,7 @@ import org.matrix.android.sdk.flow.flow class SpaceListViewModel @AssistedInject constructor( @Assisted initialState: SpaceListViewState, - private val appStateHandler: AppStateHandler, + private val spaceStateHandler: SpaceStateHandler, private val session: Session, private val vectorPreferences: VectorPreferences, private val autoAcceptInvites: AutoAcceptInvites, @@ -85,8 +85,7 @@ class SpaceListViewModel @AssistedInject constructor( } observeSpaceSummaries() -// observeSelectionState() - appStateHandler.selectedSpaceFlow + spaceStateHandler.getSelectedSpaceFlow() .distinctUntilChanged() .setOnEach { selectedSpaceOption -> copy( @@ -219,7 +218,7 @@ class SpaceListViewModel @AssistedInject constructor( if (state.selectedSpace?.roomId != action.spaceSummary?.roomId) { analyticsTracker.capture(Interaction(null, null, Interaction.Name.SpacePanelSwitchSpace)) setState { copy(selectedSpace = action.spaceSummary) } - appStateHandler.setCurrentSpace(action.spaceSummary?.roomId) + spaceStateHandler.setCurrentSpace(action.spaceSummary?.roomId) _viewEvents.post(SpaceListViewEvents.CloseDrawer) } else { analyticsTracker.capture(Interaction(null, null, Interaction.Name.SpacePanelSelectedSpace)) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceMenuViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceMenuViewModel.kt index 7b53b09187..6b1f9f88d5 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceMenuViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceMenuViewModel.kt @@ -24,7 +24,7 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.EmptyViewEvents @@ -50,7 +50,7 @@ import timber.log.Timber class SpaceMenuViewModel @AssistedInject constructor( @Assisted val initialState: SpaceMenuState, val session: Session, - val appStateHandler: AppStateHandler + val spaceStateHandler: SpaceStateHandler ) : VectorViewModel(initialState) { @AssistedFactory @@ -73,9 +73,9 @@ class SpaceMenuViewModel @AssistedInject constructor( it.getOrNull()?.let { if (it.membership == Membership.LEAVE) { setState { copy(leavingState = Success(Unit)) } - if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) { + if (spaceStateHandler.getSafeActiveSpaceId() == initialState.spaceId) { // switch to home? - appStateHandler.setCurrentSpace(null, session) + spaceStateHandler.setCurrentSpace(null, session) } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedViewModel.kt index 7413386709..800447d4c5 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedViewModel.kt @@ -24,7 +24,7 @@ import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import im.vector.app.AppStateHandler +import im.vector.app.SpaceStateHandler import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.EmptyViewEvents @@ -53,7 +53,7 @@ import timber.log.Timber class SpaceLeaveAdvancedViewModel @AssistedInject constructor( @Assisted val initialState: SpaceLeaveAdvanceViewState, private val session: Session, - private val appStateHandler: AppStateHandler + private val spaceStateHandler: SpaceStateHandler ) : VectorViewModel(initialState) { init { @@ -75,19 +75,19 @@ class SpaceLeaveAdvancedViewModel @AssistedInject constructor( } setState { copy(spaceSummary = spaceSummary) } - session.getRoom(initialState.spaceId)?.let { room -> - room.flow().liveRoomSummary() - .unwrap() - .onEach { - if (it.membership == Membership.LEAVE) { - setState { copy(leaveState = Success(Unit)) } - if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) { - // switch to home? - appStateHandler.setCurrentSpace(null, session) - } + session.getRoom(initialState.spaceId) + ?.flow() + ?.liveRoomSummary() + ?.unwrap() + ?.onEach { + if (it.membership == Membership.LEAVE) { + setState { copy(leaveState = Success(Unit)) } + if (spaceStateHandler.getSafeActiveSpaceId() == initialState.spaceId) { + // switch to home? + spaceStateHandler.setCurrentSpace(null, session) } - }.launchIn(viewModelScope) - } + } + }?.launchIn(viewModelScope) viewModelScope.launch { val children = session.roomService().getRoomSummaries( diff --git a/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt b/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt new file mode 100644 index 0000000000..36d372cfac --- /dev/null +++ b/vector/src/test/java/im/vector/app/SpaceStateHandlerImplTest.kt @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022 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 + +import im.vector.app.test.fakes.FakeActiveSessionDataSource +import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeAnalyticsTracker +import im.vector.app.test.fakes.FakeSession +import im.vector.app.test.fakes.FakeUiStateRepository +import im.vector.app.test.fixtures.RoomSummaryFixture.aRoomSummary +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Test + +internal class SpaceStateHandlerImplTest { + + private val spaceId = "spaceId" + private val spaceSummary = aRoomSummary(spaceId) + private val session = FakeSession.withRoomSummary(spaceSummary) + + private val sessionDataSource = FakeActiveSessionDataSource() + private val uiStateRepository = FakeUiStateRepository() + private val activeSessionHolder = FakeActiveSessionHolder(session) + private val analyticsTracker = FakeAnalyticsTracker() + + private val spaceStateHandler = SpaceStateHandlerImpl( + sessionDataSource.instance, + uiStateRepository, + activeSessionHolder.instance, + analyticsTracker, + ) + + @Test + fun `given selected space doesn't exist, when getCurrentSpace, then return null`() { + val currentSpace = spaceStateHandler.getCurrentSpace() + + currentSpace shouldBe null + } + + @Test + fun `given selected space exists, when getCurrentSpace, then return selected space`() { + spaceStateHandler.setCurrentSpace(spaceId, session) + + val currentSpace = spaceStateHandler.getCurrentSpace() + + currentSpace shouldBe spaceSummary + } + + @Test + fun `given persistNow is true, when setCurrentSpace, then immediately persist to ui state`() { + spaceStateHandler.setCurrentSpace(spaceId, session, persistNow = true) + + uiStateRepository.verifyStoreSelectedSpace(spaceId, session) + } + + @Test + fun `given persistNow is false, when setCurrentSpace, then don't immediately persist to ui state`() { + spaceStateHandler.setCurrentSpace(spaceId, session, persistNow = false) + + uiStateRepository.verifyStoreSelectedSpace(spaceId, session, inverse = true) + } + + @Test + fun `given is forward navigation and no current space, when setCurrentSpace, then null added to backstack`() { + spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = true) + + val backstack = spaceStateHandler.getSpaceBackstack() + + backstack.size shouldBe 1 + backstack.first() shouldBe null + } + + @Test + fun `given is forward navigation and is in space, when setCurrentSpace, then previous space added to backstack`() { + spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = true) + spaceStateHandler.setCurrentSpace("secondSpaceId", session, isForwardNavigation = true) + + val backstack = spaceStateHandler.getSpaceBackstack() + + backstack.size shouldBe 2 + backstack shouldBeEqualTo listOf(null, spaceId) + } + + @Test + fun `given is not forward navigation, when setCurrentSpace, then previous space not added to backstack`() { + spaceStateHandler.setCurrentSpace(spaceId, session, isForwardNavigation = false) + + val backstack = spaceStateHandler.getSpaceBackstack() + + backstack.size shouldBe 0 + } + + @Test + fun `when setCurrentSpace, then space is emitted to selectedSpaceFlow`() = runTest { + spaceStateHandler.setCurrentSpace(spaceId, session) + + val currentSpace = spaceStateHandler.getSelectedSpaceFlow().first().orNull() + + currentSpace shouldBeEqualTo spaceSummary + } + + @Test + fun `given current space exists, when getSafeActiveSpaceId, then return current space id`() { + spaceStateHandler.setCurrentSpace(spaceId, session) + + val activeSpaceId = spaceStateHandler.getSafeActiveSpaceId() + + activeSpaceId shouldBeEqualTo spaceId + } + + @Test + fun `given current space doesn't exist, when getSafeActiveSpaceId, then return current null`() { + val activeSpaceId = spaceStateHandler.getSafeActiveSpaceId() + + activeSpaceId shouldBe null + } +} 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 65295af3dd..18af88ba0f 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 @@ -23,11 +23,14 @@ import im.vector.app.features.session.VectorSessionStore import im.vector.app.test.testCoroutineDispatchers import io.mockk.coEvery import io.mockk.coJustRun +import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.getRoomSummary import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService import org.matrix.android.sdk.api.session.profile.ProfileService +import org.matrix.android.sdk.api.session.room.model.RoomSummary class FakeSession( val fakeCryptoService: FakeCryptoService = FakeCryptoService(), @@ -67,4 +70,11 @@ class FakeSession( this@FakeSession.startSyncing(any()) } } + + companion object { + + fun withRoomSummary(roomSummary: RoomSummary) = FakeSession().apply { + every { getRoomSummary(any()) } returns roomSummary + } + } } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeUiStateRepository.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeUiStateRepository.kt new file mode 100644 index 0000000000..4e8af9042c --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeUiStateRepository.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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 im.vector.app.features.ui.UiStateRepository +import io.mockk.justRun +import io.mockk.mockk +import io.mockk.verify +import org.matrix.android.sdk.api.session.Session + +class FakeUiStateRepository : UiStateRepository by mockk() { + + init { + justRun { storeSelectedSpace(any(), any()) } + } + + fun verifyStoreSelectedSpace(roomId: String, session: Session, inverse: Boolean = false) { + verify(inverse = inverse) { storeSelectedSpace(roomId, session.sessionId) } + } +} diff --git a/vector/src/test/java/im/vector/app/test/fixtures/RoomSummaryFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/RoomSummaryFixture.kt new file mode 100644 index 0000000000..ee37dac618 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fixtures/RoomSummaryFixture.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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.fixtures + +import org.matrix.android.sdk.api.session.room.model.RoomSummary + +object RoomSummaryFixture { + + fun aRoomSummary(roomId: String) = RoomSummary( + roomId, + isEncrypted = false, + encryptionEventTs = 0, + typingUsers = emptyList(), + ) +}