Fix / last selected space-group not restored after restart

This commit is contained in:
Valere 2021-04-26 09:46:29 +02:00
parent 1ce7085ca9
commit d186b73c90
11 changed files with 57 additions and 95 deletions

View File

@ -19,6 +19,7 @@ package im.vector.app
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import arrow.core.Option
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.settings.VectorPreferences
@ -30,7 +31,6 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
@ -57,23 +57,18 @@ class AppStateHandler @Inject constructor(
private val compositeDisposable = CompositeDisposable()
private val selectedSpaceDataSource = BehaviorDataSource(
// TODO get that from latest persisted?
if (vectorPreferences.labSpaces())
RoomGroupingMethod.BySpace(null)
else RoomGroupingMethod.ByLegacyGroup(null)
)
private val selectedSpaceDataSource = BehaviorDataSource<Option<RoomGroupingMethod>>(Option.empty())
val selectedRoomGroupingObservable = selectedSpaceDataSource.observe()
fun getCurrentRoomGroupingMethod(): RoomGroupingMethod = selectedSpaceDataSource.currentValue ?: RoomGroupingMethod.BySpace(null)
fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? = selectedSpaceDataSource.currentValue?.orNull()
fun setCurrentSpace(spaceId: String?, session: Session? = null) {
val uSession = session ?: activeSessionHolder.getSafeActiveSession()
if (selectedSpaceDataSource.currentValue is RoomGroupingMethod.BySpace
&& spaceId == selectedSpaceDataSource.currentValue?.space()?.roomId) return
if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace
&& spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return
val spaceSum = spaceId?.let { uSession?.getRoomSummary(spaceId) }
selectedSpaceDataSource.post(RoomGroupingMethod.BySpace(spaceSum))
selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum)))
if (spaceId != null) {
GlobalScope.launch {
tryOrNull {
@ -85,10 +80,10 @@ class AppStateHandler @Inject constructor(
fun setCurrentGroup(groupId: String?, session: Session? = null) {
val uSession = session ?: activeSessionHolder.getSafeActiveSession()
if (selectedSpaceDataSource.currentValue is RoomGroupingMethod.ByLegacyGroup
&& groupId == selectedSpaceDataSource.currentValue?.group()?.groupId) return
if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.ByLegacyGroup
&& groupId == selectedSpaceDataSource.currentValue?.orNull()?.group()?.groupId) return
val activeGroup = groupId?.let { uSession?.getGroupSummary(groupId) }
selectedSpaceDataSource.post(RoomGroupingMethod.ByLegacyGroup(activeGroup))
selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.ByLegacyGroup(activeGroup)))
if (groupId != null) {
GlobalScope.launch {
tryOrNull {
@ -99,19 +94,17 @@ class AppStateHandler @Inject constructor(
}
init {
sessionDataSource.observe()
.distinctUntilChanged()
.subscribe {
// sessionDataSource could already return a session while acitveSession holder still returns null
it.orNull()?.let { session ->
Timber.w("VAL: Latest method is space? ${uiStateRepository.isGroupingMethodSpace(session.sessionId)}")
if (uiStateRepository.isGroupingMethodSpace(session.sessionId)) {
uiStateRepository.getSelectedSpace(session.sessionId)?.let { selectedSpaceId ->
Timber.w("VAL: Latest selected space: $selectedSpaceId")
uiStateRepository.getSelectedSpace(session.sessionId).let { selectedSpaceId ->
setCurrentSpace(selectedSpaceId, session)
}
} else {
uiStateRepository.getSelectedGroup(session.sessionId)?.let { selectedGroupId ->
uiStateRepository.getSelectedGroup(session.sessionId).let { selectedGroupId ->
setCurrentGroup(selectedGroupId, session)
}
}
@ -119,15 +112,14 @@ class AppStateHandler @Inject constructor(
}.also {
compositeDisposable.add(it)
}
// restore current space from ui state
}
fun safeActiveSpaceId(): String? {
return (selectedSpaceDataSource.currentValue as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId
return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId
}
fun safeActiveGroupId(): String? {
return (selectedSpaceDataSource.currentValue as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@ -137,18 +129,15 @@ class AppStateHandler @Inject constructor(
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun entersBackground() {
compositeDisposable.clear()
Timber.w("VAL: entersBackground session: ${ activeSessionHolder.getSafeActiveSession()?.myUserId}")
val session = activeSessionHolder.getSafeActiveSession() ?: return
when (val currentMethod = selectedSpaceDataSource.currentValue ?: RoomGroupingMethod.BySpace(null)) {
when (val currentMethod = selectedSpaceDataSource.currentValue?.orNull() ?: RoomGroupingMethod.BySpace(null)) {
is RoomGroupingMethod.BySpace -> {
uiStateRepository.storeGroupingMethod(true, session)
Timber.w("VAL: Store selected space: ${currentMethod.spaceSummary?.roomId}")
uiStateRepository.storeSelectedSpace(currentMethod.spaceSummary?.roomId, session)
uiStateRepository.storeGroupingMethod(true, session.sessionId)
uiStateRepository.storeSelectedSpace(currentMethod.spaceSummary?.roomId, session.sessionId)
}
is RoomGroupingMethod.ByLegacyGroup -> {
uiStateRepository.storeGroupingMethod(false, session)
Timber.w("VAL: Store group space: ${currentMethod.groupSummary?.groupId}")
uiStateRepository.storeSelectedGroup(currentMethod.groupSummary?.groupId, session)
uiStateRepository.storeGroupingMethod(false, session.sessionId)
uiStateRepository.storeSelectedGroup(currentMethod.groupSummary?.groupId, session.sessionId)
}
}
}

View File

@ -140,7 +140,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
.subscribe {
setState {
copy(
roomGroupingMethod = it
roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null)
)
}
}

View File

@ -92,10 +92,12 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
this.activeSpaceId = ActiveSpaceFilter.ActiveSpace(null)
}
)
val invites = session.getRoomSummaries(roomSummaryQueryParams {
this.memberships = listOf(Membership.INVITE)
this.activeSpaceId = ActiveSpaceFilter.ActiveSpace(null)
}).size
val invites = session.getRoomSummaries(
roomSummaryQueryParams {
this.memberships = listOf(Membership.INVITE)
this.activeSpaceId = ActiveSpaceFilter.ActiveSpace(null)
}
).size
setState {
copy(
homeSpaceUnread = RoomAggregateNotificationCount(

View File

@ -71,14 +71,13 @@ class RoomListViewModel @Inject constructor(
}
init {
Timber.w("VAL: RoomListViewModel INIT")
observeMembershipChanges()
appStateHandler.selectedRoomGroupingObservable
.distinctUntilChanged()
.execute {
copy(
currentRoomGrouping = it
currentRoomGrouping = it.invoke()?.orNull()?.let { Success(it) } ?: Loading()
)
}

View File

@ -113,7 +113,7 @@ class SpaceRoomListSectionBuilder(
appStateHandler.selectedRoomGroupingObservable
.distinctUntilChanged()
.subscribe { groupingMethod ->
val selectedSpace = groupingMethod.space()
val selectedSpace = groupingMethod.orNull()?.space()
activeSpaceAwareQueries.onEach { updater ->
updater.updateForSpaceId(selectedSpace?.roomId)
}
@ -188,7 +188,7 @@ class SpaceRoomListSectionBuilder(
appStateHandler.selectedRoomGroupingObservable
.distinctUntilChanged()
.switchMap { groupingMethod ->
val selectedSpace = groupingMethod.space()
val selectedSpace = groupingMethod.orNull()?.space()
if (selectedSpace == null) {
Observable.just(emptyList())
} else {

View File

@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
sealed class SpaceListAction : VectorViewModelAction {
data class SelectSpace(val spaceSummary: RoomSummary) : SpaceListAction()
data class SelectSpace(val spaceSummary: RoomSummary?) : SpaceListAction()
data class OpenSpaceInvite(val spaceSummary: RoomSummary) : SpaceListAction()
data class LeaveSpace(val spaceSummary: RoomSummary) : SpaceListAction()
data class ToggleExpand(val spaceSummary: RoomSummary) : SpaceListAction()

View File

@ -78,7 +78,7 @@ class SpaceListFragment @Inject constructor(
spaceController.update(state)
}
override fun onSpaceSelected(spaceSummary: RoomSummary) {
override fun onSpaceSelected(spaceSummary: RoomSummary?) {
viewModel.handle(SpaceListAction.SelectSpace(spaceSummary))
}

View File

@ -136,16 +136,13 @@ class SpaceSummaryController @Inject constructor(
}
}
summaries.firstOrNull { it.roomId == ALL_COMMUNITIES_GROUP_ID }
?.let {
val isSelected = selected is RoomGroupingMethod.BySpace && selected.space() == null
homeSpaceSummaryItem {
id(it.roomId)
selected(isSelected)
countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight))
listener { callback?.onSpaceSelected(it) }
}
}
val isSelected = selected is RoomGroupingMethod.BySpace && selected.space() == null
homeSpaceSummaryItem {
id("space_home")
selected(isSelected)
countState(UnreadCounterBadgeView.State(homeCount.totalCount, homeCount.isHighlight))
listener { callback?.onSpaceSelected(null) }
}
rootSpaces
?.sortedBy { it.displayName }
@ -180,7 +177,7 @@ class SpaceSummaryController @Inject constructor(
// it's expanded
subSpaces?.forEach { child ->
summaries.firstOrNull { it.roomId == child.childRoomId }?.let { childSum ->
val isChildSelected = selected is RoomGroupingMethod.BySpace && childSum.roomId == selected.space()?.roomId
val isChildSelected = selected is RoomGroupingMethod.BySpace && childSum.roomId == selected.space()?.roomId
spaceSummaryItem {
avatarRenderer(avatarRenderer)
id(child.childRoomId)
@ -209,7 +206,7 @@ class SpaceSummaryController @Inject constructor(
}
interface Callback {
fun onSpaceSelected(spaceSummary: RoomSummary)
fun onSpaceSelected(spaceSummary: RoomSummary?)
fun onSpaceInviteSelected(spaceSummary: RoomSummary)
fun onSpaceSettings(spaceSummary: RoomSummary)
fun onToggleExpand(spaceSummary: RoomSummary)

View File

@ -26,7 +26,6 @@ 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.RoomGroupingMethod
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
@ -46,13 +45,12 @@ 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.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.user.model.User
import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.rx.asObservable
import org.matrix.android.sdk.rx.rx
import java.util.concurrent.TimeUnit
const val ALL_COMMUNITIES_GROUP_ID = "+ALL_COMMUNITIES_GROUP_ID"
class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: SpaceListViewState,
private val appStateHandler: AppStateHandler,
private val session: Session,
@ -94,7 +92,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
.subscribe {
setState {
copy(
selectedGroupingMethod = it
selectedGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null)
)
}
}
@ -166,13 +164,9 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
private fun handleSelectSpace(action: SpaceListAction.SelectSpace) = withState { state ->
val groupingMethod = state.selectedGroupingMethod
if (groupingMethod is RoomGroupingMethod.ByLegacyGroup || groupingMethod.space()?.roomId != action.spaceSummary.roomId) {
if (groupingMethod is RoomGroupingMethod.ByLegacyGroup || groupingMethod.space()?.roomId != action.spaceSummary?.roomId) {
setState { copy(selectedGroupingMethod = RoomGroupingMethod.BySpace(action.spaceSummary)) }
if (action.spaceSummary.roomId == ALL_COMMUNITIES_GROUP_ID) {
appStateHandler.setCurrentSpace(null)
} else {
appStateHandler.setCurrentSpace(action.spaceSummary.roomId)
}
appStateHandler.setCurrentSpace(action.spaceSummary?.roomId)
_viewEvents.post(SpaceListViewEvents.OpenSpace(groupingMethod is RoomGroupingMethod.ByLegacyGroup))
}
}
@ -218,35 +212,21 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
excludeType = listOf(/**RoomType.MESSAGING,$*/
null)
}
Observable.combineLatest<RoomSummary, List<RoomSummary>, List<RoomSummary>>(
Observable.combineLatest<User?, List<RoomSummary>, List<RoomSummary>>(
session
.rx()
.liveUser(session.myUserId)
.map { optionalUser ->
RoomSummary(
roomId = ALL_COMMUNITIES_GROUP_ID,
membership = Membership.JOIN,
displayName = stringProvider.getString(R.string.group_all_communities),
avatarUrl = optionalUser.getOrNull()?.avatarUrl ?: "",
encryptionEventTs = 0,
isEncrypted = false,
typingUsers = emptyList()
)
.map {
it.getOrNull()
},
session
.rx()
.liveSpaceSummaries(spaceSummaryQueryParams),
BiFunction { allCommunityGroup, communityGroups ->
(listOf(allCommunityGroup) + communityGroups)
BiFunction { _, communityGroups ->
communityGroups
}
)
.execute { async ->
// val currentSelectedGroupId = selectedGroupingMethod?.roomId
// val newSelectedGroup = if (currentSelectedGroupId != null) {
// async()?.find { it.roomId == currentSelectedGroupId }
// } else {
// async()?.firstOrNull()
// }
copy(
asyncSpaces = async,
rootSpaces = session.spaceService().getRootSpaceSummaries()

View File

@ -20,8 +20,6 @@ import android.content.SharedPreferences
import androidx.core.content.edit
import im.vector.app.features.home.RoomListDisplayMode
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import javax.inject.Inject
/**
@ -61,22 +59,20 @@ class SharedPreferencesUiStateRepository @Inject constructor(
}
}
override fun storeSelectedSpace(spaceId: String?, sessionId: Session?) {
Timber.w("VAL: storeSelectedSpace $spaceId")
sharedPreferences.edit(true) {
override fun storeSelectedSpace(spaceId: String?, sessionId: String) {
sharedPreferences.edit(true) {
putString("$KEY_SELECTED_SPACE@$sessionId", spaceId)
}
}
override fun storeSelectedGroup(groupId: String?, sessionId: Session?) {
Timber.w("VAL: storeSelectedSpace $groupId")
override fun storeSelectedGroup(groupId: String?, sessionId: String) {
sharedPreferences.edit(true) {
putString("$KEY_SELECTED_GROUP@$sessionId", groupId)
}
}
override fun storeGroupingMethod(isSpace: Boolean, sessionId: Session?) {
sharedPreferences.edit(true) {
override fun storeGroupingMethod(isSpace: Boolean, sessionId: String) {
sharedPreferences.edit(true) {
putBoolean("$KEY_SELECTED_METHOD@$sessionId", isSpace)
}
}

View File

@ -17,7 +17,6 @@
package im.vector.app.features.ui
import im.vector.app.features.home.RoomListDisplayMode
import org.matrix.android.sdk.api.session.Session
/**
* This interface is used to persist UI state across application restart
@ -33,10 +32,10 @@ interface UiStateRepository {
fun storeDisplayMode(displayMode: RoomListDisplayMode)
fun storeSelectedSpace(spaceId: String?, sessionId: Session?)
fun storeSelectedGroup(groupId: String?, sessionId: Session?)
fun storeSelectedSpace(spaceId: String?, sessionId: String)
fun storeSelectedGroup(groupId: String?, sessionId: String)
fun storeGroupingMethod(isSpace: Boolean, sessionId: Session?)
fun storeGroupingMethod(isSpace: Boolean, sessionId: String)
fun getSelectedSpace(sessionId: String): String?
fun getSelectedGroup(sessionId: String): String?