mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-18 20:29:10 +03:00
new app layouts invites (#6911)
This commit is contained in:
parent
225d05e0be
commit
70cfe00271
18 changed files with 625 additions and 1 deletions
1
changelog.d/6889.wip
Normal file
1
changelog.d/6889.wip
Normal file
|
@ -0,0 +1 @@
|
|||
[App Layout] new room invites screen
|
|
@ -349,6 +349,7 @@
|
|||
<activity android:name=".features.location.live.map.LiveLocationMapViewActivity" />
|
||||
<activity android:name=".features.settings.font.FontScaleSettingActivity"/>
|
||||
<activity android:name=".features.call.dialpad.PstnDialActivity" />
|
||||
<activity android:name=".features.home.room.list.home.invites.InvitesActivity"/>
|
||||
|
||||
<!-- Services -->
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsV
|
|||
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.home.room.list.home.invites.InvitesViewModel
|
||||
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(HomeRoomListViewModel::class)
|
||||
fun homeRoomListViewModel(factory: HomeRoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(InvitesViewModel::class)
|
||||
fun invitesViewModel(factory: InvitesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.features.home.room.list.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -48,6 +49,8 @@ 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.filter.HomeFilteredRoomsController
|
||||
import im.vector.app.features.home.room.list.home.filter.HomeRoomFilter
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesActivity
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesCounterController
|
||||
import im.vector.app.features.home.room.list.home.recent.RecentRoomCarouselController
|
||||
import im.vector.app.features.spaces.SpaceListBottomSheet
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -66,6 +69,7 @@ class HomeRoomListFragment :
|
|||
@Inject lateinit var roomSummaryItemFactory: RoomSummaryItemFactory
|
||||
@Inject lateinit var userPreferencesProvider: UserPreferencesProvider
|
||||
@Inject lateinit var recentRoomCarouselController: RecentRoomCarouselController
|
||||
@Inject lateinit var invitesCounterController: InvitesCounterController
|
||||
|
||||
private val roomListViewModel: HomeRoomListViewModel by fragmentViewModel()
|
||||
private lateinit var sharedQuickActionsViewModel: RoomListQuickActionsSharedActionViewModel
|
||||
|
@ -266,9 +270,19 @@ class HomeRoomListFragment :
|
|||
controller.submitList(list)
|
||||
}
|
||||
}.adapter
|
||||
is HomeRoomSection.InvitesCountData -> invitesCounterController.also { controller ->
|
||||
controller.clickListener = ::onInvitesCounterClicked
|
||||
section.count.observe(viewLifecycleOwner) { count ->
|
||||
controller.submitData(count)
|
||||
}
|
||||
}.adapter
|
||||
}
|
||||
}
|
||||
|
||||
private fun onInvitesCounterClicked() {
|
||||
startActivity(Intent(activity, InvitesActivity::class.java))
|
||||
}
|
||||
|
||||
private fun onRoomFilterChanged(filter: HomeRoomFilter) {
|
||||
roomListViewModel.handle(HomeRoomListAction.ChangeRoomFilter(filter))
|
||||
}
|
||||
|
@ -285,6 +299,7 @@ class HomeRoomListFragment :
|
|||
override fun onDestroyView() {
|
||||
views.roomListView.cleanup()
|
||||
recentRoomCarouselController.listener = null
|
||||
invitesCounterController.clickListener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.app.features.home.room.list.home
|
||||
|
||||
import androidx.lifecycle.map
|
||||
import androidx.paging.PagedList
|
||||
import arrow.core.toOption
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
|
@ -100,9 +101,9 @@ class HomeRoomListViewModel @AssistedInject constructor(
|
|||
|
||||
private fun configureSections() = viewModelScope.launch {
|
||||
val newSections = mutableSetOf<HomeRoomSection>()
|
||||
newSections.add(getInvitesCountSection())
|
||||
|
||||
val areSettingsEnabled = preferencesStore.areRecentsEnabledFlow.first()
|
||||
|
||||
if (areSettingsEnabled) {
|
||||
newSections.add(getRecentRoomsSection())
|
||||
}
|
||||
|
@ -127,6 +128,19 @@ class HomeRoomListViewModel @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getInvitesCountSection(): HomeRoomSection.InvitesCountData {
|
||||
val builder = RoomSummaryQueryParams.Builder().also {
|
||||
it.memberships = listOf(Membership.INVITE)
|
||||
}
|
||||
|
||||
val liveCount = session.roomService().getRoomSummariesLive(
|
||||
builder.build(),
|
||||
RoomSortOrder.ACTIVITY
|
||||
).map { it.count() }
|
||||
|
||||
return HomeRoomSection.InvitesCountData(liveCount)
|
||||
}
|
||||
|
||||
private suspend fun getFilteredRoomsSection(): HomeRoomSection.RoomSummaryData {
|
||||
val builder = RoomSummaryQueryParams.Builder().also {
|
||||
it.memberships = listOf(Membership.JOIN)
|
||||
|
|
|
@ -32,4 +32,8 @@ sealed class HomeRoomSection {
|
|||
data class RecentRoomsData(
|
||||
val list: LiveData<List<RoomSummary>>
|
||||
) : HomeRoomSection()
|
||||
|
||||
data class InvitesCountData(
|
||||
val count: LiveData<Int>
|
||||
) : HomeRoomSection()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.ClickListener
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
|
||||
@EpoxyModelClass
|
||||
abstract class InviteCounterItem : VectorEpoxyModel<InviteCounterItem.Holder>(R.layout.item_invites_count) {
|
||||
|
||||
@EpoxyAttribute var invitesCount: Int = 0
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.view.setOnClickListener(listener)
|
||||
holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(invitesCount, true))
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.invites_count_badge)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
sealed class InvitesAction : VectorViewModelAction {
|
||||
data class AcceptInvitation(val roomSummary: RoomSummary) : InvitesAction()
|
||||
data class RejectInvitation(val roomSummary: RoomSummary) : InvitesAction()
|
||||
}
|
|
@ -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.features.home.room.list.home.invites
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleBinding
|
||||
|
||||
@AndroidEntryPoint
|
||||
class InvitesActivity : VectorBaseActivity<ActivitySimpleBinding>() {
|
||||
|
||||
override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater)
|
||||
|
||||
override fun initUiAndData() {
|
||||
if (isFirstCreation()) {
|
||||
addFragment(views.simpleFragmentContainer, InvitesFragment::class.java)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import com.airbnb.epoxy.EpoxyModel
|
||||
import com.airbnb.epoxy.paging.PagedListEpoxyController
|
||||
import im.vector.app.core.utils.createUIHandler
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
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.RoomSummaryItemPlaceHolder_
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import javax.inject.Inject
|
||||
|
||||
class InvitesController @Inject constructor(
|
||||
private val roomSummaryItemFactory: RoomSummaryItemFactory,
|
||||
) : PagedListEpoxyController<RoomSummary>(
|
||||
// Important it must match the PageList builder notify Looper
|
||||
modelBuildingHandler = createUIHandler()
|
||||
) {
|
||||
|
||||
var roomChangeMembershipStates: Map<String, ChangeMembershipState>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
requestForcedModelBuild()
|
||||
}
|
||||
|
||||
var listener: RoomListListener? = null
|
||||
|
||||
override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> {
|
||||
item ?: return RoomSummaryItemPlaceHolder_().apply { id(currentPosition) }
|
||||
return roomSummaryItemFactory.create(item, roomChangeMembershipStates.orEmpty(), emptySet(), RoomListDisplayMode.ROOMS, listener)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
class InvitesCounterController @Inject constructor(
|
||||
val stringProvider: StringProvider
|
||||
) : EpoxyController() {
|
||||
|
||||
private var count = 0
|
||||
var clickListener: (() -> Unit)? = null
|
||||
|
||||
override fun buildModels() {
|
||||
val host = this
|
||||
if (count != 0) {
|
||||
inviteCounterItem {
|
||||
id("invites_counter")
|
||||
invitesCount(host.count)
|
||||
listener { host.clickListener?.invoke() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun submitData(count: Int?) {
|
||||
this.count = count ?: 0
|
||||
requestModelBuild()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentInvitesBinding
|
||||
import im.vector.app.features.analytics.plan.ViewRoom
|
||||
import im.vector.app.features.home.room.list.RoomListListener
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class InvitesFragment : VectorBaseFragment<FragmentInvitesBinding>(), RoomListListener {
|
||||
|
||||
@Inject lateinit var controller: InvitesController
|
||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||
|
||||
private val viewModel by fragmentViewModel(InvitesViewModel::class)
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentInvitesBinding {
|
||||
return FragmentInvitesBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupToolbar(views.invitesToolbar)
|
||||
.allowBack()
|
||||
|
||||
views.invitesRecycler.configureWith(controller)
|
||||
controller.listener = this
|
||||
|
||||
viewModel.onEach(InvitesViewState::roomMembershipChanges) {
|
||||
controller.roomChangeMembershipStates = it
|
||||
}
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is InvitesViewEvents.Failure -> showFailure(it.throwable)
|
||||
is InvitesViewEvents.OpenRoom -> handleOpenRoom(it.roomSummary, it.shouldCloseInviteView)
|
||||
InvitesViewEvents.Close -> handleClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleClose() {
|
||||
requireActivity().finish()
|
||||
}
|
||||
|
||||
private fun handleOpenRoom(roomSummary: RoomSummary, shouldCloseInviteView: Boolean) {
|
||||
navigator.openRoom(
|
||||
context = requireActivity(),
|
||||
roomId = roomSummary.roomId,
|
||||
isInviteAlreadyAccepted = true,
|
||||
trigger = ViewRoom.Trigger.RoomList // #6508
|
||||
)
|
||||
if (shouldCloseInviteView) {
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidate(): Unit = withState(viewModel) { state ->
|
||||
super.invalidate()
|
||||
|
||||
state.pagedList?.observe(viewLifecycleOwner) { list ->
|
||||
controller.submitList(list)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRejectRoomInvitation(room: RoomSummary) {
|
||||
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(room.roomId) }
|
||||
viewModel.handle(InvitesAction.RejectInvitation(room))
|
||||
}
|
||||
|
||||
override fun onAcceptRoomInvitation(room: RoomSummary) {
|
||||
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(room.roomId) }
|
||||
viewModel.handle(InvitesAction.AcceptInvitation(room))
|
||||
}
|
||||
|
||||
override fun onJoinSuggestedRoom(room: SpaceChildInfo) = Unit
|
||||
|
||||
override fun onSuggestedRoomClicked(room: SpaceChildInfo) = Unit
|
||||
|
||||
override fun onRoomClicked(room: RoomSummary) = Unit
|
||||
|
||||
override fun onRoomLongClicked(room: RoomSummary): Boolean = false
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
sealed class InvitesViewEvents : VectorViewEvents {
|
||||
data class Failure(val throwable: Throwable) : InvitesViewEvents()
|
||||
data class OpenRoom(val roomSummary: RoomSummary, val shouldCloseInviteView: Boolean) : InvitesViewEvents()
|
||||
object Close : InvitesViewEvents()
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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.invites
|
||||
|
||||
import androidx.paging.PagedList
|
||||
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.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.RoomSortOrder
|
||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import timber.log.Timber
|
||||
|
||||
class InvitesViewModel @AssistedInject constructor(
|
||||
@Assisted val initialState: InvitesViewState,
|
||||
private val session: Session,
|
||||
) : VectorViewModel<InvitesViewState, InvitesAction, InvitesViewEvents>(initialState) {
|
||||
|
||||
private val pagedListConfig = PagedList.Config.Builder()
|
||||
.setPageSize(10)
|
||||
.setInitialLoadSizeHint(20)
|
||||
.setEnablePlaceholders(true)
|
||||
.setPrefetchDistance(10)
|
||||
.build()
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<InvitesViewModel, InvitesViewState> {
|
||||
override fun create(initialState: InvitesViewState): InvitesViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<InvitesViewModel, InvitesViewState> by hiltMavericksViewModelFactory()
|
||||
|
||||
init {
|
||||
observeInvites()
|
||||
}
|
||||
|
||||
override fun handle(action: InvitesAction) {
|
||||
when (action) {
|
||||
is InvitesAction.AcceptInvitation -> handleAcceptInvitation(action)
|
||||
is InvitesAction.RejectInvitation -> handleRejectInvitation(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRejectInvitation(action: InvitesAction.RejectInvitation) = withState { state ->
|
||||
val roomId = action.roomSummary.roomId
|
||||
val roomMembershipChange = state.roomMembershipChanges[roomId]
|
||||
if (roomMembershipChange?.isInProgress().orFalse()) {
|
||||
// Request already sent, should not happen
|
||||
Timber.w("Try to left an already leaving or joining room. Should not happen")
|
||||
return@withState
|
||||
}
|
||||
|
||||
val shouldCloseInviteView = state.pagedList?.value?.size == 1
|
||||
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
session.roomService().leaveRoom(roomId)
|
||||
// We do not update the rejectingRoomsIds here, because, the room is not rejected yet regarding the sync data.
|
||||
// Instead, we wait for the room to be rejected
|
||||
// Known bug: if the user is invited again (after rejecting the first invitation), the loading will be displayed instead of the buttons.
|
||||
// If we update the state, the button will be displayed again, so it's not ideal...
|
||||
if (shouldCloseInviteView) {
|
||||
_viewEvents.post(InvitesViewEvents.Close)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
// Notify the user
|
||||
_viewEvents.post(InvitesViewEvents.Failure(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAcceptInvitation(action: InvitesAction.AcceptInvitation) = withState { state ->
|
||||
val roomId = action.roomSummary.roomId
|
||||
val roomMembershipChange = state.roomMembershipChanges[roomId]
|
||||
if (roomMembershipChange?.isInProgress().orFalse()) {
|
||||
// Request already sent, should not happen
|
||||
Timber.w("Try to join an already joining room. Should not happen")
|
||||
return@withState
|
||||
}
|
||||
// close invites view when navigate to a room from the last one invite
|
||||
|
||||
val shouldCloseInviteView = state.pagedList?.value?.size == 1
|
||||
|
||||
_viewEvents.post(InvitesViewEvents.OpenRoom(action.roomSummary, shouldCloseInviteView))
|
||||
|
||||
// quick echo
|
||||
setState {
|
||||
copy(
|
||||
roomMembershipChanges = roomMembershipChanges.mapValues {
|
||||
if (it.key == roomId) {
|
||||
ChangeMembershipState.Joining
|
||||
} else {
|
||||
it.value
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeInvites() {
|
||||
val builder = RoomSummaryQueryParams.Builder().also {
|
||||
it.memberships = listOf(Membership.INVITE)
|
||||
}
|
||||
val pagedList = session.roomService().getPagedRoomSummariesLive(
|
||||
queryParams = builder.build(),
|
||||
pagedListConfig = pagedListConfig,
|
||||
sortOrder = RoomSortOrder.ACTIVITY
|
||||
)
|
||||
|
||||
setState {
|
||||
copy(pagedList = pagedList)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.invites
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.paging.PagedList
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
||||
data class InvitesViewState(
|
||||
val pagedList: LiveData<PagedList<RoomSummary>>? = null,
|
||||
val roomMembershipChanges: Map<String, ChangeMembershipState> = emptyMap(),
|
||||
) : MavericksState
|
36
vector/src/main/res/layout/fragment_invites.xml
Normal file
36
vector/src/main/res/layout/fragment_invites.xml
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/invites_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
app:title="@string/invites_title" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/invites_recycler"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:fastScrollEnabled="true"
|
||||
android:overScrollMode="always"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/appBarLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
48
vector/src/main/res/layout/item_invites_count.xml
Normal file
48
vector/src/main/res/layout/item_invites_count.xml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?vctr_toolbar_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/invites_count_badge"
|
||||
style="@style/Widget.Vector.TextView.Micro"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="16dp"
|
||||
android:minHeight="16dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="?colorOnError"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:text="4"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/invites_count_title"
|
||||
style="@style/Widget.Vector.TextView.Body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/invites_title"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="?colorSecondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/invites_count_badge"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -441,6 +441,9 @@
|
|||
<string name="system_alerts_header">"System Alerts"</string>
|
||||
<string name="suggested_header">Suggested Rooms</string>
|
||||
|
||||
<!-- Invites fragment -->
|
||||
<string name="invites_title">Invites</string>
|
||||
|
||||
<!-- People fragment -->
|
||||
<string name="direct_chats_header">Conversations</string>
|
||||
<string name="matrix_only_filter">Matrix contacts only</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue