AutoAcceptInvite: refact and hide behind flag

This commit is contained in:
ganfra 2021-06-18 17:24:51 +02:00
parent 646f00f3fc
commit 6b10406622
19 changed files with 325 additions and 82 deletions

View file

@ -125,6 +125,12 @@ interface RoomService {
*/
suspend fun deleteRoomAlias(roomAlias: String)
/**
* Return the current local changes membership for the given room.
* see [getChangeMembershipsLive] for more details.
*/
fun getChangeMemberships(roomIdOrAlias: String): ChangeMembershipState
/**
* Return a live data of all local changes membership that happened since the session has been opened.
* It allows you to track this in your client to known what is currently being processed by the SDK.

View file

@ -386,4 +386,7 @@ internal abstract class SessionModule {
@Binds
abstract fun bindEventSenderProcessor(processor: EventSenderProcessorCoroutine): EventSenderProcessor
}

View file

@ -134,6 +134,10 @@ internal class DefaultRoomService @Inject constructor(
deleteRoomAliasTask.execute(DeleteRoomAliasTask.Params(roomAlias))
}
override fun getChangeMemberships(roomIdOrAlias: String): ChangeMembershipState {
return roomChangeMembershipStateDataSource.getState(roomIdOrAlias)
}
override fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>> {
return roomChangeMembershipStateDataSource.getLiveStates()
}

View file

@ -21,6 +21,7 @@ import androidx.lifecycle.MutableLiveData
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.internal.session.SessionScope
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
/**
@ -30,7 +31,7 @@ import javax.inject.Inject
internal class RoomChangeMembershipStateDataSource @Inject constructor() {
private val mutableLiveStates = MutableLiveData<Map<String, ChangeMembershipState>>(emptyMap())
private val states = HashMap<String, ChangeMembershipState>()
private val states = ConcurrentHashMap<String, ChangeMembershipState>()
/**
* This will update local states to be synced with the server.

View file

@ -54,6 +54,10 @@ internal class DefaultJoinRoomTask @Inject constructor(
) : JoinRoomTask {
override suspend fun execute(params: JoinRoomTask.Params) {
val currentState = roomChangeMembershipStateDataSource.getState(params.roomIdOrAlias)
if (currentState.isInProgress() || currentState == ChangeMembershipState.Joined) {
return
}
roomChangeMembershipStateDataSource.updateState(params.roomIdOrAlias, ChangeMembershipState.Joining)
val joinRoomResponse = try {
executeRequest(globalErrorReceiver) {

View file

@ -22,22 +22,16 @@ 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.invite.InvitesAcceptor
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.ui.UiStateRepository
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
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.members.ChangeMembershipState
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.rx.rx
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@ -58,7 +52,8 @@ fun RoomGroupingMethod.group() = (this as? RoomGroupingMethod.ByLegacyGroup)?.gr
class AppStateHandler @Inject constructor(
private val sessionDataSource: ActiveSessionDataSource,
private val uiStateRepository: UiStateRepository,
private val activeSessionHolder: ActiveSessionHolder
private val activeSessionHolder: ActiveSessionHolder,
private val invitesAcceptor: InvitesAcceptor
) : LifecycleObserver {
private val compositeDisposable = CompositeDisposable()
@ -102,13 +97,13 @@ class AppStateHandler @Inject constructor(
}
}
private fun observeActiveSession(){
private fun observeActiveSession() {
sessionDataSource.observe()
.distinctUntilChanged()
.subscribe {
// sessionDataSource could already return a session while activeSession holder still returns null
it.orNull()?.let { session ->
observeInvitesForAutoAccept(session)
invitesAcceptor.onSessionActive(session)
if (uiStateRepository.isGroupingMethodSpace(session.sessionId)) {
setCurrentSpace(uiStateRepository.getSelectedSpace(session.sessionId), session)
} else {
@ -120,41 +115,6 @@ class AppStateHandler @Inject constructor(
}
}
private fun observeInvitesForAutoAccept(session: Session?) {
if (session == null) return
val roomQueryParams = roomSummaryQueryParams {
this.memberships = listOf(Membership.INVITE)
}
val rxSession = session.rx()
Observable
.combineLatest(
rxSession.liveRoomSummaries(roomQueryParams).debounce(1, TimeUnit.SECONDS),
rxSession.liveRoomChangeMembershipState().debounce(1, TimeUnit.SECONDS),
{ invitedRooms, membershipsChanged ->
val roomIdsToJoin = mutableListOf<String>()
for (room in invitedRooms) {
val roomMembershipChanged = membershipsChanged[room.roomId] ?: ChangeMembershipState.Unknown
if (roomMembershipChanged != ChangeMembershipState.Joined && !roomMembershipChanged.isInProgress()) {
roomIdsToJoin.add(room.roomId)
}
}
roomIdsToJoin
}
)
.doOnNext { roomIdsToJoin ->
session.coroutineScope.launch {
for (roomId in roomIdsToJoin) {
Timber.v("Auto accept invite for room: $roomId")
tryOrNull { session.joinRoom(roomId) }
}
}
}
.subscribe()
.also {
compositeDisposable.add(it)
}
}
fun safeActiveSpaceId(): String? {
return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId
}

View file

@ -50,6 +50,7 @@ import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
import im.vector.app.features.home.room.list.RoomListModule
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.invite.InviteUsersToRoomActivity
import im.vector.app.features.invite.VectorInviteView
import im.vector.app.features.link.LinkHandlerActivity
@ -122,6 +123,7 @@ interface ScreenComponent {
fun errorFormatter(): ErrorFormatter
fun uiStateRepository(): UiStateRepository
fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
fun autoAcceptInvites(): AutoAcceptInvites
/* ==========================================================================================
* Activities

View file

@ -42,6 +42,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorPr
import im.vector.app.features.home.room.detail.timeline.helper.RoomSummariesHolder
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.VectorHtmlCompressor
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.notifications.NotifiableEventResolver
@ -160,6 +161,8 @@ interface VectorComponent {
fun pinLocker(): PinLocker
fun autoAcceptInvites(): AutoAcceptInvites
fun webRtcCallManager(): WebRtcCallManager
fun roomSummaryHolder(): RoomSummariesHolder

View file

@ -25,6 +25,8 @@ import dagger.Module
import dagger.Provides
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.invite.CompileTimeAutoAcceptInvites
import im.vector.app.features.navigation.DefaultNavigator
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinCodeStore
@ -105,4 +107,7 @@ abstract class VectorModule {
@Binds
abstract fun bindPinCodeStore(store: SharedPrefPinCodeStore): PinCodeStore
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
}

View file

@ -31,6 +31,7 @@ import im.vector.app.features.call.dialpad.DialPadLookup
import im.vector.app.features.call.lookup.CallProtocolsChecker
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.createdirect.DirectRoomHelper
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.ui.UiStateRepository
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
@ -56,7 +57,8 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
private val uiStateRepository: UiStateRepository,
private val callManager: WebRtcCallManager,
private val directRoomHelper: DirectRoomHelper,
private val appStateHandler: AppStateHandler)
private val appStateHandler: AppStateHandler,
private val autoAcceptInvites: AutoAcceptInvites)
: VectorViewModel<HomeDetailViewState, HomeDetailAction, HomeDetailViewEvents>(initialState),
CallProtocolsChecker.Listener {
@ -204,8 +206,25 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
}
is RoomGroupingMethod.BySpace -> {
val activeSpaceRoomId = groupingMethod.spaceSummary?.roomId
val dmInvites = 0
val roomsInvite = 0
var dmInvites = 0
var roomsInvite = 0
if(!autoAcceptInvites.hideInvites) {
dmInvites = session.getRoomSummaries(
roomSummaryQueryParams {
memberships = listOf(Membership.INVITE)
roomCategoryFilter = RoomCategoryFilter.ONLY_DM
activeSpaceFilter = activeSpaceRoomId?.let { ActiveSpaceFilter.ActiveSpace(it) } ?: ActiveSpaceFilter.None
}
).size
roomsInvite = session.getRoomSummaries(
roomSummaryQueryParams {
memberships = listOf(Membership.INVITE)
roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(groupingMethod.spaceSummary?.roomId)
}
).size
}
val dmRooms = session.getNotificationCountForRooms(
roomSummaryQueryParams {

View file

@ -29,6 +29,7 @@ import im.vector.app.RoomGroupingMethod
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
@ -54,7 +55,8 @@ data class CountInfo(
class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initialState: UnreadMessagesState,
session: Session,
private val vectorPreferences: VectorPreferences,
appStateHandler: AppStateHandler)
appStateHandler: AppStateHandler,
private val autoAcceptInvites: AutoAcceptInvites)
: VectorViewModel<UnreadMessagesState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedFactory
@ -92,7 +94,17 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
this.activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null)
}
)
val invites = 0
val invites = if (autoAcceptInvites.hideInvites) {
0
} else {
session.getRoomSummaries(
roomSummaryQueryParams {
this.memberships = listOf(Membership.INVITE)
this.activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(null)
}
).size
}
copy(
homeSpaceUnread = RoomAggregateNotificationCount(
counts.notificationCount + invites,
@ -124,8 +136,13 @@ class UnreadMessagesSharedViewModel @AssistedInject constructor(@Assisted initia
is RoomGroupingMethod.BySpace -> {
val selectedSpace = appStateHandler.safeActiveSpaceId()
val inviteCount = 0
val inviteCount = if (autoAcceptInvites.hideInvites) {
0
} else {
session.getRoomSummaries(
roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
).size
}
val totalCount = session.getNotificationCountForRooms(
roomSummaryQueryParams {
this.memberships = listOf(Membership.JOIN)

View file

@ -22,6 +22,7 @@ import im.vector.app.R
import im.vector.app.RoomGroupingMethod
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.RoomListDisplayMode
import im.vector.app.features.invite.AutoAcceptInvites
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
@ -38,6 +39,7 @@ class GroupRoomListSectionBuilder(
val stringProvider: StringProvider,
val viewModelScope: CoroutineScope,
val appStateHandler: AppStateHandler,
private val autoAcceptInvites: AutoAcceptInvites,
val onDisposable: (Disposable) -> Unit,
val onUdpatable: (UpdatableLivePageResult) -> Unit
) : RoomListSectionBuilder {
@ -48,15 +50,15 @@ class GroupRoomListSectionBuilder(
val actualGroupId = appStateHandler.safeActiveGroupId()
when (mode) {
RoomListDisplayMode.PEOPLE -> {
RoomListDisplayMode.PEOPLE -> {
// 3 sections Invites / Fav / Dms
buildPeopleSections(sections, activeGroupAwareQueries, actualGroupId)
}
RoomListDisplayMode.ROOMS -> {
RoomListDisplayMode.ROOMS -> {
// 5 sections invites / Fav / Rooms / Low Priority / Server notice
buildRoomsSections(sections, activeGroupAwareQueries, actualGroupId)
}
RoomListDisplayMode.FILTERED -> {
RoomListDisplayMode.FILTERED -> {
// Used when searching for rooms
withQueryParams(
{
@ -73,17 +75,18 @@ class GroupRoomListSectionBuilder(
)
}
RoomListDisplayMode.NOTIFICATIONS -> {
addSection(
sections,
activeGroupAwareQueries,
R.string.invitations_header,
true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ALL
it.activeGroupId = actualGroupId
if (!autoAcceptInvites.hideInvites) {
addSection(
sections,
activeGroupAwareQueries,
R.string.invitations_header,
true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ALL
it.activeGroupId = actualGroupId
}
}
addSection(
sections,
activeGroupAwareQueries,
@ -115,6 +118,18 @@ class GroupRoomListSectionBuilder(
private fun buildRoomsSections(sections: MutableList<RoomsSection>,
activeSpaceAwareQueries: MutableList<UpdatableLivePageResult>,
actualGroupId: String?) {
if (!autoAcceptInvites.hideInvites) {
addSection(
sections,
activeSpaceAwareQueries,
R.string.invitations_header,
true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
it.activeGroupId = actualGroupId
}
}
addSection(
sections,
@ -170,6 +185,17 @@ class GroupRoomListSectionBuilder(
activeSpaceAwareQueries: MutableList<UpdatableLivePageResult>,
actualGroupId: String?
) {
if (!autoAcceptInvites.hideInvites) {
addSection(sections,
activeSpaceAwareQueries,
R.string.invitations_header,
true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM
it.activeGroupId = actualGroupId
}
}
addSection(
sections,

View file

@ -30,6 +30,7 @@ import im.vector.app.RoomGroupingMethod
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -49,7 +50,8 @@ class RoomListViewModel @Inject constructor(
private val session: Session,
private val stringProvider: StringProvider,
private val appStateHandler: AppStateHandler,
private val vectorPreferences: VectorPreferences
private val vectorPreferences: VectorPreferences,
private val autoAcceptInvites: AutoAcceptInvites
) : VectorViewModel<RoomListViewState, RoomListAction, RoomListViewEvents>(initialState) {
interface Factory {
@ -126,6 +128,7 @@ class RoomListViewModel @Inject constructor(
appStateHandler,
viewModelScope,
suggestedRoomJoiningState,
autoAcceptInvites,
{
it.disposeOnClear()
},
@ -140,6 +143,7 @@ class RoomListViewModel @Inject constructor(
stringProvider,
viewModelScope,
appStateHandler,
autoAcceptInvites,
{
it.disposeOnClear()
},

View file

@ -18,6 +18,7 @@ package im.vector.app.features.home.room.list
import im.vector.app.AppStateHandler
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.session.Session
import javax.inject.Inject
@ -26,16 +27,18 @@ import javax.inject.Provider
class RoomListViewModelFactory @Inject constructor(private val session: Provider<Session>,
private val appStateHandler: AppStateHandler,
private val stringProvider: StringProvider,
private val vectorPreferences: VectorPreferences)
private val vectorPreferences: VectorPreferences,
private val autoAcceptInvites: AutoAcceptInvites)
: RoomListViewModel.Factory {
override fun create(initialState: RoomListViewState): RoomListViewModel {
return RoomListViewModel(
initialState,
session.get(),
stringProvider,
appStateHandler,
vectorPreferences
initialState = initialState,
session = session.get(),
stringProvider = stringProvider,
appStateHandler = appStateHandler,
vectorPreferences = vectorPreferences,
autoAcceptInvites = autoAcceptInvites
)
}
}

View file

@ -26,6 +26,7 @@ import im.vector.app.AppStateHandler
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.RoomListDisplayMode
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.space
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
@ -50,6 +51,7 @@ class SpaceRoomListSectionBuilder(
val appStateHandler: AppStateHandler,
val viewModelScope: CoroutineScope,
private val suggestedRoomJoiningState: LiveData<Map<String, Async<Unit>>>,
private val autoAcceptInvites: AutoAcceptInvites,
val onDisposable: (Disposable) -> Unit,
val onUdpatable: (UpdatableLivePageResult) -> Unit,
val onlyOrphansInHome: Boolean = false
@ -66,13 +68,13 @@ class SpaceRoomListSectionBuilder(
val sections = mutableListOf<RoomsSection>()
val activeSpaceAwareQueries = mutableListOf<RoomListViewModel.ActiveSpaceQueryUpdater>()
when (mode) {
RoomListDisplayMode.PEOPLE -> {
RoomListDisplayMode.PEOPLE -> {
buildDmSections(sections, activeSpaceAwareQueries)
}
RoomListDisplayMode.ROOMS -> {
RoomListDisplayMode.ROOMS -> {
buildRoomsSections(sections, activeSpaceAwareQueries)
}
RoomListDisplayMode.FILTERED -> {
RoomListDisplayMode.FILTERED -> {
withQueryParams(
{
it.memberships = Membership.activeMemberships()
@ -88,6 +90,23 @@ class SpaceRoomListSectionBuilder(
)
}
RoomListDisplayMode.NOTIFICATIONS -> {
if (!autoAcceptInvites.hideInvites) {
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
countRoomAsNotif = true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ALL
}
}
addSection(
sections = sections,
@ -121,6 +140,20 @@ class SpaceRoomListSectionBuilder(
}
private fun buildRoomsSections(sections: MutableList<RoomsSection>, activeSpaceAwareQueries: MutableList<RoomListViewModel.ActiveSpaceQueryUpdater>) {
if (!autoAcceptInvites.hideInvites) {
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL,
countRoomAsNotif = true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_ROOMS
}
}
addSection(
sections,
activeSpaceAwareQueries,
@ -226,6 +259,18 @@ class SpaceRoomListSectionBuilder(
}
private fun buildDmSections(sections: MutableList<RoomsSection>, activeSpaceAwareQueries: MutableList<RoomListViewModel.ActiveSpaceQueryUpdater>) {
if (!autoAcceptInvites.hideInvites) {
addSection(sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
spaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL,
countRoomAsNotif = true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_DM
}
}
addSection(sections,
activeSpaceAwareQueries,
@ -350,7 +395,7 @@ class SpaceRoomListSectionBuilder(
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(currentSpace)
)
}
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> {
if (currentSpace == null) {
copy(
activeSpaceFilter = ActiveSpaceFilter.None
@ -361,7 +406,7 @@ class SpaceRoomListSectionBuilder(
)
}
}
RoomListViewModel.SpaceFilterStrategy.NONE -> this
RoomListViewModel.SpaceFilterStrategy.NONE -> this
}
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2021 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.invite
import javax.inject.Inject
interface AutoAcceptInvites {
val isEnabled: Boolean
val hideInvites: Boolean
}
class CompileTimeAutoAcceptInvites @Inject constructor() : AutoAcceptInvites {
override val isEnabled = true
override val hideInvites = false
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2021 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.invite
import im.vector.app.features.session.coroutineScope
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.rx.rx
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
/**
* This class is responsible for auto accepting invites.
* It's listening to invites and membershipChanges so it can retry automatically if needed.
* This mechanism will be on only if AutoAcceptInvites.isEnabled is true.
*/
@Singleton
class InvitesAcceptor @Inject constructor(private val autoAcceptInvites: AutoAcceptInvites) : Session.Listener {
private val disposables = HashMap<String, Disposable>()
private val semaphore = Semaphore(1)
fun onSessionActive(session: Session) {
if (!autoAcceptInvites.isEnabled) {
return
}
if (disposables.containsKey(session.sessionId)) {
return
}
session.addListener(this)
val roomQueryParams = roomSummaryQueryParams {
this.memberships = listOf(Membership.INVITE)
}
val rxSession = session.rx()
Observable
.combineLatest(
rxSession.liveRoomSummaries(roomQueryParams),
rxSession.liveRoomChangeMembershipState().debounce(1, TimeUnit.SECONDS),
{ invitedRooms, _ -> invitedRooms.map { it.roomId } }
)
.filter { it.isNotEmpty() }
.subscribe { invitedRoomIds ->
session.coroutineScope.launch {
semaphore.withPermit {
Timber.v("Invited roomIds: $invitedRoomIds")
for (roomId in invitedRoomIds) {
async { session.joinRoomSafely(roomId) }.start()
}
}
}
}
.also {
disposables[session.sessionId] = it
}
}
private suspend fun Session.joinRoomSafely(roomId: String) {
val roomMembershipChanged = getChangeMemberships(roomId)
if (roomMembershipChanged != ChangeMembershipState.Joined && !roomMembershipChanged.isInProgress()) {
try {
Timber.v("Try auto join room: $roomId")
joinRoom(roomId)
} catch (failure: Throwable) {
Timber.v("Failed auto join room: $roomId")
}
}
}
override fun onSessionStopped(session: Session) {
session.removeListener(this)
disposables.remove(session.sessionId)?.dispose()
}
}

View file

@ -27,6 +27,7 @@ import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.FirstThrottler
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
import me.gujun.android.span.span
import org.matrix.android.sdk.api.session.Session
@ -50,7 +51,8 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
private val activeSessionDataSource: ActiveSessionDataSource,
private val iconLoader: IconLoader,
private val bitmapLoader: BitmapLoader,
private val outdatedDetector: OutdatedEventDetector?) {
private val outdatedDetector: OutdatedEventDetector?,
private val autoAcceptInvites: AutoAcceptInvites) {
private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY)
private var backgroundHandler: Handler
@ -254,7 +256,12 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
}
}
is InviteNotifiableEvent -> {
//invitationEvents.add(event)
if(autoAcceptInvites.hideInvites){
// Forget this event
eventIterator.remove()
}else {
invitationEvents.add(event)
}
}
is SimpleNotifiableEvent -> simpleEvents.add(event)
else -> Timber.w("Type not handled")

View file

@ -28,6 +28,7 @@ import dagger.assisted.AssistedInject
import im.vector.app.AppStateHandler
import im.vector.app.RoomGroupingMethod
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.group
import im.vector.app.space
@ -54,7 +55,8 @@ import java.util.concurrent.TimeUnit
class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: SpaceListViewState,
private val appStateHandler: AppStateHandler,
private val session: Session,
private val vectorPreferences: VectorPreferences
private val vectorPreferences: VectorPreferences,
private val autoAcceptInvites: AutoAcceptInvites
) : VectorViewModel<SpaceListViewState, SpaceListAction, SpaceListViewEvents>(initialState) {
@AssistedFactory
@ -119,7 +121,13 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
.throttleFirst(300, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.computation())
.subscribe {
val inviteCount = 0
val inviteCount = if(autoAcceptInvites.hideInvites){
0
}else {
session.getRoomSummaries(
roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
).size
}
val totalCount = session.getNotificationCountForRooms(
roomSummaryQueryParams {
this.memberships = listOf(Membership.JOIN)