mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
new room list implementation for EditLayout (#6618)
This commit is contained in:
parent
f37034c18e
commit
45bbf74db3
9 changed files with 560 additions and 3 deletions
|
@ -61,6 +61,7 @@ import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
|
|||
import im.vector.app.features.home.room.detail.TimelineFragment
|
||||
import im.vector.app.features.home.room.detail.search.SearchFragment
|
||||
import im.vector.app.features.home.room.list.RoomListFragment
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListFragment
|
||||
import im.vector.app.features.home.room.threads.list.views.ThreadListFragment
|
||||
import im.vector.app.features.location.LocationPreviewFragment
|
||||
import im.vector.app.features.location.LocationSharingFragment
|
||||
|
@ -1041,4 +1042,9 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(LocationPreviewFragment::class)
|
||||
fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(HomeRoomListFragment::class)
|
||||
fun binHomeRoomListFragment(fragment: HomeRoomListFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHist
|
|||
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsViewModel
|
||||
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomViewModel
|
||||
import im.vector.app.features.home.room.list.RoomListViewModel
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListViewModel
|
||||
import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
|
||||
import im.vector.app.features.invite.InviteUsersToRoomViewModel
|
||||
import im.vector.app.features.location.LocationSharingViewModel
|
||||
|
@ -618,4 +619,9 @@ interface MavericksViewModelModule {
|
|||
@IntoMap
|
||||
@MavericksViewModelKey(FontScaleSettingViewModel::class)
|
||||
fun fontScaleSettingViewModelFactory(factory: FontScaleSettingViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(HomeRoomListViewModel::class)
|
||||
fun homeRoomListViewModel(factory: HomeRoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import im.vector.app.core.ui.views.CurrentCallsView
|
|||
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
|
||||
import im.vector.app.core.ui.views.KeysBackupBanner
|
||||
import im.vector.app.databinding.FragmentHomeDetailBinding
|
||||
import im.vector.app.features.VectorFeatures
|
||||
import im.vector.app.features.call.SharedKnownCallsViewModel
|
||||
import im.vector.app.features.call.VectorCallActivity
|
||||
import im.vector.app.features.call.dialpad.DialPadFragment
|
||||
|
@ -48,6 +49,7 @@ import im.vector.app.features.call.webrtc.WebRtcCallManager
|
|||
import im.vector.app.features.home.room.list.RoomListFragment
|
||||
import im.vector.app.features.home.room.list.RoomListParams
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListFragment
|
||||
import im.vector.app.features.popup.PopupAlertManager
|
||||
import im.vector.app.features.popup.VerificationVectorAlert
|
||||
import im.vector.app.features.settings.VectorLocale
|
||||
|
@ -66,7 +68,8 @@ class HomeDetailFragment @Inject constructor(
|
|||
private val alertManager: PopupAlertManager,
|
||||
private val callManager: WebRtcCallManager,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val appStateHandler: AppStateHandler
|
||||
private val appStateHandler: AppStateHandler,
|
||||
private val vectorFeatures: VectorFeatures,
|
||||
) : VectorBaseFragment<FragmentHomeDetailBinding>(),
|
||||
KeysBackupBanner.Delegate,
|
||||
CurrentCallsView.Callback,
|
||||
|
@ -352,9 +355,13 @@ class HomeDetailFragment @Inject constructor(
|
|||
if (fragmentToShow == null) {
|
||||
when (tab) {
|
||||
is HomeTab.RoomList -> {
|
||||
if (vectorFeatures.isNewAppLayoutEnabled()) {
|
||||
add(R.id.roomListContainer, HomeRoomListFragment::class.java, null, fragmentTag)
|
||||
} else {
|
||||
val params = RoomListParams(tab.displayMode)
|
||||
add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
|
||||
}
|
||||
}
|
||||
is HomeTab.DialPad -> {
|
||||
add(R.id.roomListContainer, createDialPadFragment(), fragmentTag)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||
|
||||
sealed class HomeRoomListAction : VectorViewModelAction {
|
||||
data class SelectRoom(val roomSummary: RoomSummary) : HomeRoomListAction()
|
||||
data class ChangeRoomNotificationState(val roomId: String, val notificationState: RoomNotificationState) : HomeRoomListAction()
|
||||
data class ToggleTag(val roomId: String, val tag: String) : HomeRoomListAction()
|
||||
data class LeaveRoom(val roomId: String) : HomeRoomListAction()
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.airbnb.epoxy.EpoxyControllerAdapter
|
||||
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.LayoutManagerStateRestorer
|
||||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.databinding.FragmentRoomListBinding
|
||||
import im.vector.app.features.analytics.plan.ViewRoom
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.list.RoomListAnimator
|
||||
import im.vector.app.features.home.room.list.RoomListListener
|
||||
import im.vector.app.features.home.room.list.RoomSummaryItemFactory
|
||||
import im.vector.app.features.home.room.list.RoomSummaryPagedController
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||
import javax.inject.Inject
|
||||
|
||||
class HomeRoomListFragment @Inject constructor(
|
||||
private val roomSummaryItemFactory: RoomSummaryItemFactory,
|
||||
private val userPreferencesProvider: UserPreferencesProvider
|
||||
) : VectorBaseFragment<FragmentRoomListBinding>(),
|
||||
RoomListListener {
|
||||
|
||||
private val roomListViewModel: HomeRoomListViewModel by fragmentViewModel()
|
||||
private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel
|
||||
private var concatAdapter = ConcatAdapter()
|
||||
private var modelBuildListener: OnModelBuildFinishedListener? = null
|
||||
|
||||
private lateinit var stateRestorer: LayoutManagerStateRestorer
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomListBinding {
|
||||
return FragmentRoomListBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||
sharedActionViewModel
|
||||
.stream()
|
||||
.onEach { handleQuickActions(it) }
|
||||
.launchIn(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
views.stateView.contentView = views.roomListView
|
||||
views.stateView.state = StateView.State.Loading
|
||||
|
||||
roomListViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is HomeRoomListViewEvents.Loading -> showLoading(it.message)
|
||||
is HomeRoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||
is HomeRoomListViewEvents.SelectRoom -> handleSelectRoom(it, it.isInviteAlreadyAccepted)
|
||||
is HomeRoomListViewEvents.Done -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
setupRecyclerView()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
views.roomListView.layoutManager = layoutManager
|
||||
views.roomListView.itemAnimator = RoomListAnimator()
|
||||
layoutManager.recycleChildrenOnDetach = true
|
||||
|
||||
modelBuildListener = OnModelBuildFinishedListener { it.dispatchTo(stateRestorer) }
|
||||
|
||||
roomListViewModel.sections.onEach { sections ->
|
||||
setUpAdapters(sections)
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
views.roomListView.adapter = concatAdapter
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(roomListViewModel) { state ->
|
||||
views.stateView.state = state.state
|
||||
}
|
||||
|
||||
private fun setUpAdapters(sections: Set<HomeRoomSection>) {
|
||||
sections.forEach {
|
||||
concatAdapter.addAdapter(getAdapterForData(it))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleQuickActions(quickAction: RoomListQuickActionsSharedAction) {
|
||||
when (quickAction) {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES_NOISY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsAll -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MENTIONS_ONLY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMute -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Settings -> {
|
||||
navigator.openRoomProfile(requireActivity(), quickAction.roomId)
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Favorite -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_FAVOURITE))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.LowPriority -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_LOW_PRIORITY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Leave -> {
|
||||
roomListViewModel.handle(HomeRoomListAction.LeaveRoom(quickAction.roomId))
|
||||
promptLeaveRoom(quickAction.roomId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun promptLeaveRoom(roomId: String) {
|
||||
val isPublicRoom = roomListViewModel.isPublicRoom(roomId)
|
||||
val message = buildString {
|
||||
append(getString(R.string.room_participants_leave_prompt_msg))
|
||||
if (!isPublicRoom) {
|
||||
append("\n\n")
|
||||
append(getString(R.string.room_participants_leave_private_warning))
|
||||
}
|
||||
}
|
||||
MaterialAlertDialogBuilder(requireContext(), if (isPublicRoom) 0 else R.style.ThemeOverlay_Vector_MaterialAlertDialog_Destructive)
|
||||
.setTitle(R.string.room_participants_leave_prompt_title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.action_leave) { _, _ ->
|
||||
roomListViewModel.handle(HomeRoomListAction.LeaveRoom(roomId))
|
||||
}
|
||||
.setNegativeButton(R.string.action_cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun getAdapterForData(data: HomeRoomSection): EpoxyControllerAdapter {
|
||||
return when (data) {
|
||||
is HomeRoomSection.RoomSummaryData -> {
|
||||
RoomSummaryPagedController(
|
||||
roomSummaryItemFactory,
|
||||
RoomListDisplayMode.ROOMS
|
||||
).also { controller ->
|
||||
controller.listener = this
|
||||
data.list.observe(viewLifecycleOwner) { list ->
|
||||
controller.submitList(list)
|
||||
}
|
||||
}.adapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSelectRoom(event: HomeRoomListViewEvents.SelectRoom, isInviteAlreadyAccepted: Boolean) {
|
||||
navigator.openRoom(
|
||||
context = requireActivity(),
|
||||
roomId = event.roomSummary.roomId,
|
||||
isInviteAlreadyAccepted = isInviteAlreadyAccepted,
|
||||
trigger = ViewRoom.Trigger.RoomList
|
||||
)
|
||||
}
|
||||
|
||||
// region RoomListListener
|
||||
|
||||
override fun onRoomClicked(room: RoomSummary) {
|
||||
roomListViewModel.handle(HomeRoomListAction.SelectRoom(room))
|
||||
}
|
||||
|
||||
override fun onRoomLongClicked(room: RoomSummary): Boolean {
|
||||
userPreferencesProvider.neverShowLongClickOnRoomHelpAgain()
|
||||
RoomListQuickActionsBottomSheet
|
||||
.newInstance(room.roomId)
|
||||
.show(childFragmentManager, "ROOM_LIST_QUICK_ACTIONS")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onRejectRoomInvitation(room: RoomSummary) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onAcceptRoomInvitation(room: RoomSummary) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onJoinSuggestedRoom(room: SpaceChildInfo) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onSuggestedRoomClicked(room: SpaceChildInfo) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
sealed class HomeRoomListViewEvents : VectorViewEvents {
|
||||
data class Loading(val message: CharSequence? = null) : HomeRoomListViewEvents()
|
||||
data class Failure(val throwable: Throwable) : HomeRoomListViewEvents()
|
||||
object Done : HomeRoomListViewEvents()
|
||||
data class SelectRoom(val roomSummary: RoomSummary, val isInviteAlreadyAccepted: Boolean = false) : HomeRoomListViewEvents()
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import androidx.paging.PagedList
|
||||
import arrow.core.toOption
|
||||
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.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.home.room.list.RoomListViewModel
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.query.SpaceFilter
|
||||
import org.matrix.android.sdk.api.query.toActiveSpaceOrOrphanRooms
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
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 vectorPreferences: VectorPreferences,
|
||||
) : VectorViewModel<HomeRoomListViewState, HomeRoomListAction, HomeRoomListViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<HomeRoomListViewModel, HomeRoomListViewState> {
|
||||
override fun create(initialState: HomeRoomListViewState): HomeRoomListViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<HomeRoomListViewModel, HomeRoomListViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
private val pagedListConfig = PagedList.Config.Builder()
|
||||
.setPageSize(10)
|
||||
.setInitialLoadSizeHint(20)
|
||||
.setEnablePlaceholders(true)
|
||||
.setPrefetchDistance(10)
|
||||
.build()
|
||||
|
||||
private val _sections = MutableSharedFlow<Set<HomeRoomSection>>(replay = 1)
|
||||
val sections = _sections.asSharedFlow()
|
||||
|
||||
init {
|
||||
configureSections()
|
||||
}
|
||||
|
||||
private fun configureSections() {
|
||||
val newSections = mutableSetOf<HomeRoomSection>()
|
||||
|
||||
newSections.add(getAllRoomsSection())
|
||||
|
||||
viewModelScope.launch {
|
||||
_sections.emit(newSections)
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(state = StateView.State.Content)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllRoomsSection(): HomeRoomSection.RoomSummaryData {
|
||||
val builder = RoomSummaryQueryParams.Builder().also {
|
||||
it.memberships = listOf(Membership.JOIN)
|
||||
}
|
||||
|
||||
val filteredPagedRoomSummariesLive = session.roomService().getFilteredPagedRoomSummariesLive(
|
||||
builder.build(),
|
||||
pagedListConfig
|
||||
)
|
||||
|
||||
appStateHandler.selectedSpaceFlow
|
||||
.distinctUntilChanged()
|
||||
.onStart {
|
||||
emit(appStateHandler.getCurrentSpace().toOption())
|
||||
}
|
||||
.onEach { selectedSpaceOption ->
|
||||
val selectedSpace = selectedSpaceOption.orNull()
|
||||
val strategy = if (!vectorPreferences.prefSpacesShowAllRoomInHome()) {
|
||||
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
|
||||
} else {
|
||||
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
|
||||
}
|
||||
filteredPagedRoomSummariesLive.queryParams = filteredPagedRoomSummariesLive.queryParams.copy(
|
||||
spaceFilter = getSpaceFilter(selectedSpaceId = selectedSpace?.roomId, strategy)
|
||||
)
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
return HomeRoomSection.RoomSummaryData(
|
||||
list = filteredPagedRoomSummariesLive.livePagedList
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSpaceFilter(selectedSpaceId: String?, strategy: RoomListViewModel.SpaceFilterStrategy): SpaceFilter? {
|
||||
return when (strategy) {
|
||||
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> {
|
||||
selectedSpaceId?.toActiveSpaceOrOrphanRooms()
|
||||
}
|
||||
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> {
|
||||
selectedSpaceId?.let { SpaceFilter.ActiveSpace(it) }
|
||||
}
|
||||
RoomListViewModel.SpaceFilterStrategy.NONE -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: HomeRoomListAction) {
|
||||
when (action) {
|
||||
is HomeRoomListAction.SelectRoom -> handleSelectRoom(action)
|
||||
is HomeRoomListAction.LeaveRoom -> handleLeaveRoom(action)
|
||||
is HomeRoomListAction.ChangeRoomNotificationState -> handleChangeNotificationMode(action)
|
||||
is HomeRoomListAction.ToggleTag -> handleToggleTag(action)
|
||||
}
|
||||
}
|
||||
|
||||
fun isPublicRoom(roomId: String): Boolean {
|
||||
return session.getRoom(roomId)?.stateService()?.isPublic().orFalse()
|
||||
}
|
||||
|
||||
private fun handleSelectRoom(action: HomeRoomListAction.SelectRoom) = withState {
|
||||
_viewEvents.post(HomeRoomListViewEvents.SelectRoom(action.roomSummary, false))
|
||||
}
|
||||
|
||||
private fun handleLeaveRoom(action: HomeRoomListAction.LeaveRoom) {
|
||||
_viewEvents.post(HomeRoomListViewEvents.Loading(null))
|
||||
viewModelScope.launch {
|
||||
val value = runCatching { session.roomService().leaveRoom(action.roomId) }
|
||||
.fold({ HomeRoomListViewEvents.Done }, { HomeRoomListViewEvents.Failure(it) })
|
||||
_viewEvents.post(value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleChangeNotificationMode(action: HomeRoomListAction.ChangeRoomNotificationState) {
|
||||
val room = session.getRoom(action.roomId)
|
||||
if (room != null) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
room.roomPushRuleService().setRoomNotificationState(action.notificationState)
|
||||
} catch (failure: Exception) {
|
||||
_viewEvents.post(HomeRoomListViewEvents.Failure(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleToggleTag(action: HomeRoomListAction.ToggleTag) {
|
||||
session.getRoom(action.roomId)?.let { room ->
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
if (room.roomSummary()?.hasTag(action.tag) == false) {
|
||||
// Favorite and low priority tags are exclusive, so maybe delete the other tag first
|
||||
action.tag.otherTag()
|
||||
?.takeIf { room.roomSummary()?.hasTag(it).orFalse() }
|
||||
?.let { tagToRemove ->
|
||||
room.tagsService().deleteTag(tagToRemove)
|
||||
}
|
||||
|
||||
// Set the tag. We do not handle the order for the moment
|
||||
room.tagsService().addTag(action.tag, 0.5)
|
||||
} else {
|
||||
room.tagsService().deleteTag(action.tag)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(HomeRoomListViewEvents.Failure(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.otherTag(): String? {
|
||||
return when (this) {
|
||||
RoomTag.ROOM_TAG_FAVOURITE -> RoomTag.ROOM_TAG_LOW_PRIORITY
|
||||
RoomTag.ROOM_TAG_LOW_PRIORITY -> RoomTag.ROOM_TAG_FAVOURITE
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
import im.vector.app.core.platform.StateView
|
||||
|
||||
data class HomeRoomListViewState(
|
||||
val state: StateView.State = StateView.State.Loading
|
||||
) : MavericksState
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.features.home.room.list.home
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.PagedList
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
sealed class HomeRoomSection {
|
||||
data class RoomSummaryData(
|
||||
val list: LiveData<PagedList<RoomSummary>>
|
||||
) : HomeRoomSection()
|
||||
}
|
Loading…
Reference in a new issue