Mavericks 2: continue replacing Rx
This commit is contained in:
parent
0e01c64f69
commit
f72a34ed08
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.home
|
package im.vector.app.features.home
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
@ -47,6 +46,7 @@ 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.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.rx.asObservable
|
import org.matrix.android.sdk.rx.asObservable
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -95,7 +95,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
|||||||
updateShowDialPadTab()
|
updateShowDialPadTab()
|
||||||
observeDataStore()
|
observeDataStore()
|
||||||
callManager.addProtocolsCheckerListener(this)
|
callManager.addProtocolsCheckerListener(this)
|
||||||
session.rx().liveUser(session.myUserId).execute {
|
session.flow().liveUser(session.myUserId).execute {
|
||||||
copy(
|
copy(
|
||||||
myMatrixItem = it.invoke()?.getOrNull()?.toMatrixItem()
|
myMatrixItem = it.invoke()?.getOrNull()?.toMatrixItem()
|
||||||
)
|
)
|
||||||
|
@ -25,25 +25,25 @@ import com.airbnb.mvrx.Success
|
|||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import io.reactivex.Observable
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
data class UnknownDevicesState(
|
data class UnknownDevicesState(
|
||||||
val myMatrixItem: MatrixItem.UserItem? = null,
|
val myMatrixItem: MatrixItem.UserItem? = null,
|
||||||
@ -98,31 +98,31 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(@Assisted
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Observable.combineLatest<List<CryptoDeviceInfo>, List<DeviceInfo>, Optional<PrivateKeysInfo>, List<DeviceDetectionInfo>>(
|
combine(
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId),
|
session.flow().liveUserCryptoDevices(session.myUserId),
|
||||||
session.rx().liveMyDevicesInfo(),
|
session.flow().liveMyDevicesInfo(),
|
||||||
session.rx().liveCrossSigningPrivateKeys(),
|
session.flow().liveCrossSigningPrivateKeys()
|
||||||
{ cryptoList, infoList, pInfo ->
|
|
||||||
// Timber.v("## Detector trigger ${cryptoList.map { "${it.deviceId} ${it.trustLevel}" }}")
|
|
||||||
// Timber.v("## Detector trigger canCrossSign ${pInfo.get().selfSigned != null}")
|
|
||||||
infoList
|
|
||||||
.filter { info ->
|
|
||||||
// filter verified session, by checking the crypto device info
|
|
||||||
cryptoList.firstOrNull { info.deviceId == it.deviceId }?.isVerified?.not().orFalse()
|
|
||||||
}
|
|
||||||
// filter out ignored devices
|
|
||||||
.filter { !ignoredDeviceList.contains(it.deviceId) }
|
|
||||||
.sortedByDescending { it.lastSeenTs }
|
|
||||||
.map { deviceInfo ->
|
|
||||||
val deviceKnownSince = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }?.firstTimeSeenLocalTs ?: 0
|
|
||||||
DeviceDetectionInfo(
|
|
||||||
deviceInfo,
|
|
||||||
deviceKnownSince > currentSessionTs + 60_000, // short window to avoid false positive,
|
|
||||||
pInfo.getOrNull()?.selfSigned != null // adding this to pass distinct when cross sign change
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
{ cryptoList, infoList, pInfo ->
|
||||||
|
// Timber.v("## Detector trigger ${cryptoList.map { "${it.deviceId} ${it.trustLevel}" }}")
|
||||||
|
// Timber.v("## Detector trigger canCrossSign ${pInfo.get().selfSigned != null}")
|
||||||
|
infoList
|
||||||
|
.filter { info ->
|
||||||
|
// filter verified session, by checking the crypto device info
|
||||||
|
cryptoList.firstOrNull { info.deviceId == it.deviceId }?.isVerified?.not().orFalse()
|
||||||
|
}
|
||||||
|
// filter out ignored devices
|
||||||
|
.filter { !ignoredDeviceList.contains(it.deviceId) }
|
||||||
|
.sortedByDescending { it.lastSeenTs }
|
||||||
|
.map { deviceInfo ->
|
||||||
|
val deviceKnownSince = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }?.firstTimeSeenLocalTs ?: 0
|
||||||
|
DeviceDetectionInfo(
|
||||||
|
deviceInfo,
|
||||||
|
deviceKnownSince > currentSessionTs + 60_000, // short window to avoid false positive,
|
||||||
|
pInfo.getOrNull()?.selfSigned != null // adding this to pass distinct when cross sign change
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
// Timber.v("## Detector trigger passed distinct")
|
// Timber.v("## Detector trigger passed distinct")
|
||||||
@ -132,14 +132,14 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(@Assisted
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId)
|
session.flow().liveUserCryptoDevices(session.myUserId)
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.throttleLast(5_000, TimeUnit.MILLISECONDS)
|
.sample(5_000)
|
||||||
.subscribe {
|
.onEach {
|
||||||
// If we have a new crypto device change, we might want to trigger refresh of device info
|
// If we have a new crypto device change, we might want to trigger refresh of device info
|
||||||
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
||||||
}
|
}
|
||||||
.disposeOnClear()
|
.launchIn(viewModelScope)
|
||||||
|
|
||||||
// trigger a refresh of lastSeen / last Ip
|
// trigger a refresh of lastSeen / last Ip
|
||||||
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
||||||
|
@ -28,7 +28,6 @@ import com.airbnb.mvrx.Success
|
|||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay2.PublishRelay
|
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
@ -60,11 +59,11 @@ import im.vector.app.features.session.coroutineScope
|
|||||||
import im.vector.app.features.settings.VectorDataStore
|
import im.vector.app.features.settings.VectorDataStore
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.features.voice.VoicePlayerHelper
|
import im.vector.app.features.voice.VoicePlayerHelper
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import io.reactivex.schedulers.Schedulers
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filterIsInstance
|
import kotlinx.coroutines.flow.filterIsInstance
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
@ -112,8 +111,6 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -143,7 +140,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
private val eventId = initialState.eventId
|
private val eventId = initialState.eventId
|
||||||
private val invisibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsInvisible>()
|
private val invisibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsInvisible>()
|
||||||
private val visibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsVisible>()
|
private val visibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsVisible>()
|
||||||
private var timelineEvents = PublishRelay.create<List<TimelineEvent>>()
|
private var timelineEvents = MutableSharedFlow<List<TimelineEvent>>(0)
|
||||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId)
|
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId)
|
||||||
|
|
||||||
// Same lifecycle than the ViewModel (survive to screen rotation)
|
// Same lifecycle than the ViewModel (survive to screen rotation)
|
||||||
@ -1533,14 +1530,12 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getUnreadState() {
|
private fun getUnreadState() {
|
||||||
Observable
|
combine(
|
||||||
.combineLatest<List<TimelineEvent>, RoomSummary, UnreadState>(
|
timelineEvents,
|
||||||
timelineEvents.observeOn(Schedulers.computation()),
|
room.flow().liveRoomSummary().unwrap()
|
||||||
room.rx().liveRoomSummary().unwrap(),
|
) { timelineEvents, roomSummary ->
|
||||||
{ timelineEvents, roomSummary ->
|
computeUnreadState(timelineEvents, roomSummary)
|
||||||
computeUnreadState(timelineEvents, roomSummary)
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
// We don't want live update of unread so we skip when we already had a HasUnread or HasNoUnread
|
// We don't want live update of unread so we skip when we already had a HasUnread or HasNoUnread
|
||||||
.distinctUntilChanged { previous, current ->
|
.distinctUntilChanged { previous, current ->
|
||||||
when {
|
when {
|
||||||
@ -1549,10 +1544,9 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subscribe {
|
.setOnEach {
|
||||||
setState { copy(unreadState = it) }
|
copy(unreadState = it)
|
||||||
}
|
}
|
||||||
.disposeOnClear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeUnreadState(events: List<TimelineEvent>, roomSummary: RoomSummary): UnreadState {
|
private fun computeUnreadState(events: List<TimelineEvent>, roomSummary: RoomSummary): UnreadState {
|
||||||
@ -1619,7 +1613,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
||||||
timelineEvents.accept(snapshot)
|
timelineEvents.tryEmit(snapshot)
|
||||||
|
|
||||||
// PreviewUrl
|
// PreviewUrl
|
||||||
if (vectorPreferences.showUrlPreviews()) {
|
if (vectorPreferences.showUrlPreviews()) {
|
||||||
|
@ -25,20 +25,17 @@ import com.airbnb.mvrx.Success
|
|||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.functions.BiFunction
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.combineLatest
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -50,8 +47,6 @@ import org.matrix.android.sdk.api.session.profile.ProfileService
|
|||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
@ -60,8 +55,6 @@ import org.matrix.android.sdk.api.util.toMatrixItem
|
|||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.flow.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
|
||||||
|
|
||||||
class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private val initialState: RoomMemberProfileViewState,
|
class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private val initialState: RoomMemberProfileViewState,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
@ -114,7 +107,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveUserCryptoDevices(initialState.userId)
|
session.flow().liveUserCryptoDevices(initialState.userId)
|
||||||
.map {
|
.map {
|
||||||
Pair(
|
Pair(
|
||||||
it.fold(true, { prev, dev -> prev && dev.isVerified }),
|
it.fold(true, { prev, dev -> prev && dev.isVerified }),
|
||||||
@ -128,14 +121,14 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveCrossSigningInfo(initialState.userId)
|
session.flow().liveCrossSigningInfo(initialState.userId)
|
||||||
.execute {
|
.execute {
|
||||||
copy(userMXCrossSigningInfo = it.invoke()?.getOrNull())
|
copy(userMXCrossSigningInfo = it.invoke()?.getOrNull())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeIgnoredState() {
|
private fun observeIgnoredState() {
|
||||||
session.rx().liveIgnoredUsers()
|
session.flow().liveIgnoredUsers()
|
||||||
.map { ignored ->
|
.map { ignored ->
|
||||||
ignored.find {
|
ignored.find {
|
||||||
it.userId == initialState.userId
|
it.userId == initialState.userId
|
||||||
@ -252,7 +245,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||||||
val queryParams = roomMemberQueryParams {
|
val queryParams = roomMemberQueryParams {
|
||||||
this.userId = QueryStringValue.Equals(initialState.userId, QueryStringValue.Case.SENSITIVE)
|
this.userId = QueryStringValue.Equals(initialState.userId, QueryStringValue.Case.SENSITIVE)
|
||||||
}
|
}
|
||||||
room.rx().liveRoomMembers(queryParams)
|
room.flow().liveRoomMembers(queryParams)
|
||||||
.map { it.firstOrNull().toOptional() }
|
.map { it.firstOrNull().toOptional() }
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute {
|
.execute {
|
||||||
@ -312,7 +305,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||||||
roomSummaryLive.execute {
|
roomSummaryLive.execute {
|
||||||
copy(isRoomEncrypted = it.invoke()?.isEncrypted == true)
|
copy(isRoomEncrypted = it.invoke()?.isEncrypted == true)
|
||||||
}
|
}
|
||||||
roomSummaryLive.combine(powerLevelsContentLive){roomSummary, powerLevelsContent ->
|
roomSummaryLive.combine(powerLevelsContentLive) { roomSummary, powerLevelsContent ->
|
||||||
val roomName = roomSummary.toMatrixItem().getBestName()
|
val roomName = roomSummary.toMatrixItem().getBestName()
|
||||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
||||||
when (val userPowerLevel = powerLevelsHelper.getUserRole(initialState.userId)) {
|
when (val userPowerLevel = powerLevelsHelper.getUserRole(initialState.userId)) {
|
||||||
|
@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
|||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||||
import org.matrix.android.sdk.api.util.MatrixItem
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
|
|
||||||
@ -55,14 +56,14 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
session.rx().liveUserCryptoDevices(args.userId)
|
session.flow().liveUserCryptoDevices(args.userId)
|
||||||
.execute {
|
.execute {
|
||||||
copy(cryptoDevices = it).also {
|
copy(cryptoDevices = it).also {
|
||||||
refreshSelectedId()
|
refreshSelectedId()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveCrossSigningInfo(args.userId)
|
session.flow().liveCrossSigningInfo(args.userId)
|
||||||
.execute {
|
.execute {
|
||||||
copy(memberCrossSigningKey = it.invoke()?.getOrNull())
|
copy(memberCrossSigningKey = it.invoke()?.getOrNull())
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
room.rx().liveRoomSummary()
|
room.flow().liveRoomSummary()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
|
@ -38,6 +38,8 @@ import org.matrix.android.sdk.api.session.room.model.Membership
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
import org.matrix.android.sdk.rx.unwrap
|
||||||
|
|
||||||
@ -54,15 +56,14 @@ class RoomBannedMemberListViewModel @AssistedInject constructor(@Assisted initia
|
|||||||
private val room = session.getRoom(initialState.roomId)!!
|
private val room = session.getRoom(initialState.roomId)!!
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val rxRoom = room.rx()
|
|
||||||
|
|
||||||
room.rx().liveRoomSummary()
|
room.flow().liveRoomSummary()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomSummary = async)
|
copy(roomSummary = async)
|
||||||
}
|
}
|
||||||
|
|
||||||
rxRoom.liveRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.BAN) })
|
room.flow().liveRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.BAN) })
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
bannedMemberSummaries = it
|
bannedMemberSummaries = it
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package im.vector.app.features.roomprofile.members
|
package im.vector.app.features.roomprofile.members
|
||||||
|
|
||||||
|
import androidx.lifecycle.asFlow
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
@ -27,10 +28,16 @@ import im.vector.app.core.extensions.exhaustive
|
|||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.switchMap
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
|
import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
@ -44,10 +51,9 @@ import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
|||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.rx.asObservable
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.rx.mapOptional
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState,
|
class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState: RoomMemberListViewState,
|
||||||
@ -87,28 +93,28 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||||||
memberships = Membership.activeMemberships()
|
memberships = Membership.activeMemberships()
|
||||||
}
|
}
|
||||||
|
|
||||||
Observable
|
combine(
|
||||||
.combineLatest<List<RoomMemberSummary>, PowerLevelsContent, RoomMemberSummaries>(
|
room.flow().liveRoomMembers(roomMemberQueryParams),
|
||||||
room.rx().liveRoomMembers(roomMemberQueryParams),
|
room.flow()
|
||||||
room.rx()
|
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)
|
||||||
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)
|
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
||||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
.unwrap()
|
||||||
.unwrap(),
|
)
|
||||||
{ roomMembers, powerLevelsContent ->
|
{ roomMembers, powerLevelsContent ->
|
||||||
buildRoomMemberSummaries(powerLevelsContent, roomMembers)
|
buildRoomMemberSummaries(powerLevelsContent, roomMembers)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomMemberSummaries = async)
|
copy(roomMemberSummaries = async)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room.isEncrypted()) {
|
if (room.isEncrypted()) {
|
||||||
room.rx().liveRoomMembers(roomMemberQueryParams)
|
room.flow().liveRoomMembers(roomMemberQueryParams)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.flowOn(Dispatchers.Main)
|
||||||
.switchMap { membersSummary ->
|
.flatMapLatest { membersSummary ->
|
||||||
session.cryptoService().getLiveCryptoDeviceInfo(membersSummary.map { it.userId })
|
session.cryptoService().getLiveCryptoDeviceInfo(membersSummary.map { it.userId })
|
||||||
.asObservable()
|
.asFlow()
|
||||||
.doOnError { Timber.e(it) }
|
.catch { Timber.e(it) }
|
||||||
.map { deviceList ->
|
.map { deviceList ->
|
||||||
// If any key change, emit the userIds list
|
// If any key change, emit the userIds list
|
||||||
deviceList.groupBy { it.userId }.mapValues {
|
deviceList.groupBy { it.userId }.mapValues {
|
||||||
@ -147,7 +153,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
room.rx().liveRoomSummary()
|
room.flow().liveRoomSummary()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomSummary = async)
|
copy(roomSummary = async)
|
||||||
@ -155,7 +161,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeThirdPartyInvites() {
|
private fun observeThirdPartyInvites() {
|
||||||
room.rx().liveStateEvents(setOf(EventType.STATE_ROOM_THIRD_PARTY_INVITE))
|
room.flow().liveStateEvents(setOf(EventType.STATE_ROOM_THIRD_PARTY_INVITE))
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(threePidInvites = async)
|
copy(threePidInvites = async)
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ import im.vector.app.core.platform.VectorViewModel
|
|||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
import org.matrix.android.sdk.rx.unwrap
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ class RoomNotificationSettingsViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeSummary() {
|
private fun observeSummary() {
|
||||||
room.rx().liveRoomSummary()
|
room.flow().liveRoomSummary()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomSummary = async)
|
copy(roomSummary = async)
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.roomprofile.uploads
|
package im.vector.app.features.roomprofile.uploads
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -25,15 +24,15 @@ import com.airbnb.mvrx.MavericksViewModelFactory
|
|||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
|
|
||||||
class RoomUploadsViewModel @AssistedInject constructor(
|
class RoomUploadsViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: RoomUploadsViewState,
|
@Assisted initialState: RoomUploadsViewState,
|
||||||
@ -66,7 +65,7 @@ class RoomUploadsViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
room.rx().liveRoomSummary()
|
room.flow().liveRoomSummary()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(roomSummary = async)
|
copy(roomSummary = async)
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.crosssigning
|
package im.vector.app.features.settings.crosssigning
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
@ -28,8 +27,8 @@ import im.vector.app.core.platform.VectorViewModel
|
|||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.auth.ReAuthActivity
|
import im.vector.app.features.auth.ReAuthActivity
|
||||||
import im.vector.app.features.login.ReAuthHelper
|
import im.vector.app.features.login.ReAuthHelper
|
||||||
import io.reactivex.Observable
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
||||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||||
@ -38,14 +37,11 @@ import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
|||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified
|
import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
|
||||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
@ -59,26 +55,26 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
|
|||||||
) : VectorViewModel<CrossSigningSettingsViewState, CrossSigningSettingsAction, CrossSigningSettingsViewEvents>(initialState) {
|
) : VectorViewModel<CrossSigningSettingsViewState, CrossSigningSettingsAction, CrossSigningSettingsViewEvents>(initialState) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Observable.combineLatest<List<DeviceInfo>, Optional<MXCrossSigningInfo>, Pair<List<DeviceInfo>, Optional<MXCrossSigningInfo>>>(
|
combine(
|
||||||
session.rx().liveMyDevicesInfo(),
|
session.flow().liveMyDevicesInfo(),
|
||||||
session.rx().liveCrossSigningInfo(session.myUserId),
|
session.flow().liveCrossSigningInfo(session.myUserId)
|
||||||
{ myDevicesInfo, mxCrossSigningInfo ->
|
|
||||||
myDevicesInfo to mxCrossSigningInfo
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
.execute { data ->
|
{ myDevicesInfo, mxCrossSigningInfo ->
|
||||||
val crossSigningKeys = data.invoke()?.second?.getOrNull()
|
myDevicesInfo to mxCrossSigningInfo
|
||||||
val xSigningIsEnableInAccount = crossSigningKeys != null
|
}
|
||||||
val xSigningKeysAreTrusted = session.cryptoService().crossSigningService().checkUserTrust(session.myUserId).isVerified()
|
.execute { data ->
|
||||||
val xSigningKeyCanSign = session.cryptoService().crossSigningService().canCrossSign()
|
val crossSigningKeys = data.invoke()?.second?.getOrNull()
|
||||||
|
val xSigningIsEnableInAccount = crossSigningKeys != null
|
||||||
|
val xSigningKeysAreTrusted = session.cryptoService().crossSigningService().checkUserTrust(session.myUserId).isVerified()
|
||||||
|
val xSigningKeyCanSign = session.cryptoService().crossSigningService().canCrossSign()
|
||||||
|
|
||||||
copy(
|
copy(
|
||||||
crossSigningInfo = crossSigningKeys,
|
crossSigningInfo = crossSigningKeys,
|
||||||
xSigningIsEnableInAccount = xSigningIsEnableInAccount,
|
xSigningIsEnableInAccount = xSigningIsEnableInAccount,
|
||||||
xSigningKeysAreTrusted = xSigningKeysAreTrusted,
|
xSigningKeysAreTrusted = xSigningKeysAreTrusted,
|
||||||
xSigningKeyCanSign = xSigningKeyCanSign
|
xSigningKeyCanSign = xSigningKeyCanSign
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var uiaContinuation: Continuation<UIABaseAuth>? = null
|
var uiaContinuation: Continuation<UIABaseAuth>? = null
|
||||||
@ -126,7 +122,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
is CrossSigningSettingsAction.SsoAuthDone -> {
|
is CrossSigningSettingsAction.SsoAuthDone -> {
|
||||||
Timber.d("## UIA - FallBack success")
|
Timber.d("## UIA - FallBack success")
|
||||||
if (pendingAuth != null) {
|
if (pendingAuth != null) {
|
||||||
uiaContinuation?.resume(pendingAuth!!)
|
uiaContinuation?.resume(pendingAuth!!)
|
||||||
@ -134,7 +130,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
|
|||||||
uiaContinuation?.resumeWithException(IllegalArgumentException())
|
uiaContinuation?.resumeWithException(IllegalArgumentException())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is CrossSigningSettingsAction.PasswordAuthDone -> {
|
is CrossSigningSettingsAction.PasswordAuthDone -> {
|
||||||
val decryptedPass = session.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
|
val decryptedPass = session.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
|
||||||
uiaContinuation?.resume(
|
uiaContinuation?.resume(
|
||||||
UserPasswordAuth(
|
UserPasswordAuth(
|
||||||
@ -144,7 +140,7 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
CrossSigningSettingsAction.ReAuthCancelled -> {
|
CrossSigningSettingsAction.ReAuthCancelled -> {
|
||||||
Timber.d("## UIA - Reauth cancelled")
|
Timber.d("## UIA - Reauth cancelled")
|
||||||
_viewEvents.post(CrossSigningSettingsViewEvents.HideModalWaitingView)
|
_viewEvents.post(CrossSigningSettingsViewEvents.HideModalWaitingView)
|
||||||
uiaContinuation?.resumeWithException(Exception())
|
uiaContinuation?.resumeWithException(Exception())
|
||||||
|
@ -25,7 +25,9 @@ import dagger.assisted.AssistedFactory
|
|||||||
import im.vector.app.core.platform.EmptyAction
|
import im.vector.app.core.platform.EmptyAction
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||||||
isRecoverySetup = session.sharedSecretStorageService.isRecoverySetup()
|
isRecoverySetup = session.sharedSecretStorageService.isRecoverySetup()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
session.rx().liveCrossSigningInfo(session.myUserId)
|
session.flow().liveCrossSigningInfo(session.myUserId)
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
hasAccountCrossSigning = it.invoke()?.getOrNull() != null,
|
hasAccountCrossSigning = it.invoke()?.getOrNull() != null,
|
||||||
@ -56,7 +58,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId)
|
session.flow().liveUserCryptoDevices(session.myUserId)
|
||||||
.map { list ->
|
.map { list ->
|
||||||
list.firstOrNull { it.deviceId == deviceId }
|
list.firstOrNull { it.deviceId == deviceId }
|
||||||
}
|
}
|
||||||
@ -67,7 +69,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId)
|
session.flow().liveUserCryptoDevices(session.myUserId)
|
||||||
.map { it.size }
|
.map { it.size }
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
@ -79,7 +81,7 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||||||
copy(deviceInfo = Loading())
|
copy(deviceInfo = Loading())
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveMyDevicesInfo()
|
session.flow().liveMyDevicesInfo()
|
||||||
.map { devices ->
|
.map { devices ->
|
||||||
devices.firstOrNull { it.deviceId == deviceId } ?: DeviceInfo(deviceId = deviceId)
|
devices.firstOrNull { it.deviceId == deviceId } ?: DeviceInfo(deviceId = deviceId)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.settings.devices
|
package im.vector.app.features.settings.devices
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -34,31 +33,36 @@ import im.vector.app.core.platform.VectorViewModel
|
|||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.auth.ReAuthActivity
|
import im.vector.app.features.auth.ReAuthActivity
|
||||||
import im.vector.app.features.login.ReAuthHelper
|
import im.vector.app.features.login.ReAuthHelper
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.subjects.PublishSubject
|
import io.reactivex.subjects.PublishSubject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
||||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||||
|
import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
||||||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
|
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
|
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
|
||||||
import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
|
||||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
@ -118,18 +122,18 @@ class DevicesViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Observable.combineLatest<List<CryptoDeviceInfo>, List<DeviceInfo>, List<DeviceFullInfo>>(
|
combine(
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId),
|
session.flow().liveUserCryptoDevices(session.myUserId),
|
||||||
session.rx().liveMyDevicesInfo(),
|
session.flow().liveMyDevicesInfo()
|
||||||
{ cryptoList, infoList ->
|
|
||||||
infoList
|
|
||||||
.sortedByDescending { it.lastSeenTs }
|
|
||||||
.map { deviceInfo ->
|
|
||||||
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
|
||||||
DeviceFullInfo(deviceInfo, cryptoDeviceInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
{ cryptoList, infoList ->
|
||||||
|
infoList
|
||||||
|
.sortedByDescending { it.lastSeenTs }
|
||||||
|
.map { deviceInfo ->
|
||||||
|
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
||||||
|
DeviceFullInfo(deviceInfo, cryptoDeviceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
@ -137,7 +141,7 @@ class DevicesViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveCrossSigningInfo(session.myUserId)
|
session.flow().liveCrossSigningInfo(session.myUserId)
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
hasAccountCrossSigning = it.invoke()?.getOrNull() != null,
|
hasAccountCrossSigning = it.invoke()?.getOrNull() != null,
|
||||||
@ -146,24 +150,24 @@ class DevicesViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
session.cryptoService().verificationService().addListener(this)
|
session.cryptoService().verificationService().addListener(this)
|
||||||
|
|
||||||
// session.rx().liveMyDeviceInfo()
|
// session.flow().liveMyDeviceInfo()
|
||||||
// .execute {
|
// .execute {
|
||||||
// copy(
|
// copy(
|
||||||
// devices = it
|
// devices = it
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
session.rx().liveUserCryptoDevices(session.myUserId)
|
session.flow().liveUserCryptoDevices(session.myUserId)
|
||||||
.map { it.size }
|
.map { it.size }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.throttleLast(5_000, TimeUnit.MILLISECONDS)
|
.sample(5_000)
|
||||||
.subscribe {
|
.onEach {
|
||||||
// If we have a new crypto device change, we might want to trigger refresh of device info
|
// If we have a new crypto device change, we might want to trigger refresh of device info
|
||||||
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
||||||
}
|
}
|
||||||
.disposeOnClear()
|
.launchIn(viewModelScope)
|
||||||
|
|
||||||
// session.rx().liveUserCryptoDevices(session.myUserId)
|
// session.flow().liveUserCryptoDevices(session.myUserId)
|
||||||
// .execute {
|
// .execute {
|
||||||
// copy(
|
// copy(
|
||||||
// cryptoDevices = it
|
// cryptoDevices = it
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.settings.threepids
|
package im.vector.app.features.settings.threepids
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -33,15 +32,15 @@ import im.vector.app.core.resources.StringProvider
|
|||||||
import im.vector.app.core.utils.ReadOnceTrue
|
import im.vector.app.core.utils.ReadOnceTrue
|
||||||
import im.vector.app.features.auth.ReAuthActivity
|
import im.vector.app.features.auth.ReAuthActivity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
||||||
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
|
||||||
|
import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
||||||
import org.matrix.android.sdk.api.auth.UIABaseAuth
|
|
||||||
import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
@ -102,7 +101,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeThreePids() {
|
private fun observeThreePids() {
|
||||||
session.rx()
|
session.flow()
|
||||||
.liveThreePIds(true)
|
.liveThreePIds(true)
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
@ -112,7 +111,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observePendingThreePids() {
|
private fun observePendingThreePids() {
|
||||||
session.rx()
|
session.flow()
|
||||||
.livePendingThreePIds()
|
.livePendingThreePIds()
|
||||||
.execute {
|
.execute {
|
||||||
copy(
|
copy(
|
||||||
@ -131,13 +130,13 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
override fun handle(action: ThreePidsSettingsAction) {
|
override fun handle(action: ThreePidsSettingsAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is ThreePidsSettingsAction.AddThreePid -> handleAddThreePid(action)
|
is ThreePidsSettingsAction.AddThreePid -> handleAddThreePid(action)
|
||||||
is ThreePidsSettingsAction.ContinueThreePid -> handleContinueThreePid(action)
|
is ThreePidsSettingsAction.ContinueThreePid -> handleContinueThreePid(action)
|
||||||
is ThreePidsSettingsAction.SubmitCode -> handleSubmitCode(action)
|
is ThreePidsSettingsAction.SubmitCode -> handleSubmitCode(action)
|
||||||
is ThreePidsSettingsAction.CancelThreePid -> handleCancelThreePid(action)
|
is ThreePidsSettingsAction.CancelThreePid -> handleCancelThreePid(action)
|
||||||
is ThreePidsSettingsAction.DeleteThreePid -> handleDeleteThreePid(action)
|
is ThreePidsSettingsAction.DeleteThreePid -> handleDeleteThreePid(action)
|
||||||
is ThreePidsSettingsAction.ChangeUiState -> handleChangeUiState(action)
|
is ThreePidsSettingsAction.ChangeUiState -> handleChangeUiState(action)
|
||||||
ThreePidsSettingsAction.SsoAuthDone -> {
|
ThreePidsSettingsAction.SsoAuthDone -> {
|
||||||
Timber.d("## UIA - FallBack success")
|
Timber.d("## UIA - FallBack success")
|
||||||
if (pendingAuth != null) {
|
if (pendingAuth != null) {
|
||||||
uiaContinuation?.resume(pendingAuth!!)
|
uiaContinuation?.resume(pendingAuth!!)
|
||||||
@ -155,7 +154,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ThreePidsSettingsAction.ReAuthCancelled -> {
|
ThreePidsSettingsAction.ReAuthCancelled -> {
|
||||||
Timber.d("## UIA - Reauth cancelled")
|
Timber.d("## UIA - Reauth cancelled")
|
||||||
uiaContinuation?.resumeWithException(Exception())
|
uiaContinuation?.resumeWithException(Exception())
|
||||||
uiaContinuation = null
|
uiaContinuation = null
|
||||||
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ class IncomingShareViewModel @AssistedInject constructor(
|
|||||||
memberships = listOf(Membership.JOIN)
|
memberships = listOf(Membership.JOIN)
|
||||||
}
|
}
|
||||||
session
|
session
|
||||||
.rx().liveRoomSummaries(queryParams)
|
.flow().liveRoomSummaries(queryParams)
|
||||||
.execute {
|
.execute {
|
||||||
copy(roomSummaries = it)
|
copy(roomSummaries = it)
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership
|
|||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ class SpaceMenuViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
session.getRoom(initialState.spaceId)?.let { room ->
|
session.getRoom(initialState.spaceId)?.let { room ->
|
||||||
|
|
||||||
room.rx().liveRoomSummary().subscribe {
|
room.flow().liveRoomSummary().onEach {
|
||||||
it.getOrNull()?.let {
|
it.getOrNull()?.let {
|
||||||
if (it.membership == Membership.LEAVE) {
|
if (it.membership == Membership.LEAVE) {
|
||||||
setState { copy(leavingState = Success(Unit)) }
|
setState { copy(leavingState = Success(Unit)) }
|
||||||
@ -87,7 +88,7 @@ class SpaceMenuViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.disposeOnClear()
|
}.launchIn(viewModelScope)
|
||||||
|
|
||||||
PowerLevelsFlowFactory(room)
|
PowerLevelsFlowFactory(room)
|
||||||
.createFlow()
|
.createFlow()
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.spaces.leave
|
package im.vector.app.features.spaces.leave
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -31,6 +30,8 @@ import dagger.assisted.AssistedInject
|
|||||||
import im.vector.app.AppStateHandler
|
import im.vector.app.AppStateHandler
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.internal.toImmutableList
|
import okhttp3.internal.toImmutableList
|
||||||
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
|
||||||
@ -38,7 +39,8 @@ import org.matrix.android.sdk.api.query.RoomCategoryFilter
|
|||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.flow.flow
|
||||||
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
|
class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
|
||||||
@ -95,17 +97,17 @@ class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
|
|||||||
val spaceSummary = session.getRoomSummary(initialState.spaceId)
|
val spaceSummary = session.getRoomSummary(initialState.spaceId)
|
||||||
setState { copy(spaceSummary = spaceSummary) }
|
setState { copy(spaceSummary = spaceSummary) }
|
||||||
session.getRoom(initialState.spaceId)?.let { room ->
|
session.getRoom(initialState.spaceId)?.let { room ->
|
||||||
room.rx().liveRoomSummary().subscribe {
|
room.flow().liveRoomSummary()
|
||||||
it.getOrNull()?.let {
|
.unwrap()
|
||||||
if (it.membership == Membership.LEAVE) {
|
.onEach {
|
||||||
setState { copy(leaveState = Success(Unit)) }
|
if (it.membership == Membership.LEAVE) {
|
||||||
if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) {
|
setState { copy(leaveState = Success(Unit)) }
|
||||||
// switch to home?
|
if (appStateHandler.safeActiveSpaceId() == initialState.spaceId) {
|
||||||
appStateHandler.setCurrentSpace(null, session)
|
// switch to home?
|
||||||
|
appStateHandler.setCurrentSpace(null, session)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}.launchIn(viewModelScope)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.app.features.widgets
|
package im.vector.app.features.widgets
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -26,11 +25,12 @@ import com.airbnb.mvrx.MavericksViewModelFactory
|
|||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.features.widgets.permissions.WidgetPermissionsHelper
|
import im.vector.app.features.widgets.permissions.WidgetPermissionsHelper
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
@ -41,9 +41,10 @@ import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerS
|
|||||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||||
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
||||||
import org.matrix.android.sdk.rx.mapOptional
|
import org.matrix.android.sdk.flow.flow
|
||||||
|
import org.matrix.android.sdk.flow.mapOptional
|
||||||
|
import org.matrix.android.sdk.flow.unwrap
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import org.matrix.android.sdk.rx.unwrap
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
@ -118,16 +119,15 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi
|
|||||||
if (room == null) {
|
if (room == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)
|
room.flow().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)
|
||||||
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
.mapOptional { it.content.toModel<PowerLevelsContent>() }
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map {
|
.map {
|
||||||
PowerLevelsHelper(it).isUserAllowedToSend(session.myUserId, true, null)
|
PowerLevelsHelper(it).isUserAllowedToSend(session.myUserId, true, null)
|
||||||
}
|
}
|
||||||
.subscribe {
|
.setOnEach {
|
||||||
setState { copy(canManageWidgets = it) }
|
copy(canManageWidgets = it)
|
||||||
}
|
}
|
||||||
.disposeOnClear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeWidgetIfNeeded() {
|
private fun observeWidgetIfNeeded() {
|
||||||
|
@ -25,27 +25,23 @@ import com.airbnb.mvrx.MavericksViewModelFactory
|
|||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.core.platform.EmptyAction
|
import im.vector.app.core.platform.EmptyAction
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import io.reactivex.Observable
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import io.reactivex.functions.Function4
|
import kotlinx.coroutines.flow.combine
|
||||||
import io.reactivex.subjects.PublishSubject
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.flow.flow
|
||||||
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
|
||||||
import org.matrix.android.sdk.rx.rx
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
data class ServerBackupStatusViewState(
|
data class ServerBackupStatusViewState(
|
||||||
val bannerState: Async<BannerState> = Uninitialized
|
val bannerState: Async<BannerState> = Uninitialized
|
||||||
@ -91,43 +87,38 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
val keysExportedToFile = MutableLiveData<Boolean>()
|
val keysExportedToFile = MutableLiveData<Boolean>()
|
||||||
val keysBackupState = MutableLiveData<KeysBackupState>()
|
val keysBackupState = MutableLiveData<KeysBackupState>()
|
||||||
|
|
||||||
private val keyBackupPublishSubject: PublishSubject<KeysBackupState> = PublishSubject.create()
|
private val keyBackupFlow = MutableSharedFlow<KeysBackupState>(0)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
session.cryptoService().keysBackupService().addListener(this)
|
session.cryptoService().keysBackupService().addListener(this)
|
||||||
|
|
||||||
keysBackupState.value = session.cryptoService().keysBackupService().state
|
keysBackupState.value = session.cryptoService().keysBackupService().state
|
||||||
|
val liveUserAccountData = session.flow().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME))
|
||||||
Observable.combineLatest<List<UserAccountDataEvent>, Optional<MXCrossSigningInfo>, KeysBackupState, Optional<PrivateKeysInfo>, BannerState>(
|
val liveCrossSigningInfo = session.flow().liveCrossSigningInfo(session.myUserId)
|
||||||
session.rx().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME)),
|
val liveCrossSigningPrivateKeys = session.flow().liveCrossSigningPrivateKeys()
|
||||||
session.rx().liveCrossSigningInfo(session.myUserId),
|
combine(liveUserAccountData, liveCrossSigningInfo, keyBackupFlow, liveCrossSigningPrivateKeys) { _, crossSigningInfo, keyBackupState, pInfo ->
|
||||||
keyBackupPublishSubject,
|
// first check if 4S is already setup
|
||||||
session.rx().liveCrossSigningPrivateKeys(),
|
if (session.sharedSecretStorageService.isRecoverySetup()) {
|
||||||
Function4 { _, crossSigningInfo, keyBackupState, pInfo ->
|
// 4S is already setup sp we should not display anything
|
||||||
// first check if 4S is already setup
|
return@combine when (keyBackupState) {
|
||||||
if (session.sharedSecretStorageService.isRecoverySetup()) {
|
KeysBackupState.BackingUp -> BannerState.BackingUp
|
||||||
// 4S is already setup sp we should not display anything
|
else -> BannerState.Hidden
|
||||||
return@Function4 when (keyBackupState) {
|
|
||||||
KeysBackupState.BackingUp -> BannerState.BackingUp
|
|
||||||
else -> BannerState.Hidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// So recovery is not setup
|
|
||||||
// Check if cross signing is enabled and local secrets known
|
|
||||||
if (
|
|
||||||
crossSigningInfo.getOrNull() == null
|
|
||||||
|| (crossSigningInfo.getOrNull()?.isTrusted() == true
|
|
||||||
&& pInfo.getOrNull()?.allKnown().orFalse())
|
|
||||||
) {
|
|
||||||
// So 4S is not setup and we have local secrets,
|
|
||||||
return@Function4 BannerState.Setup(numberOfKeys = getNumberOfKeysToBackup())
|
|
||||||
}
|
|
||||||
|
|
||||||
BannerState.Hidden
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
.throttleLast(1000, TimeUnit.MILLISECONDS) // we don't want to flicker or catch transient states
|
|
||||||
|
// So recovery is not setup
|
||||||
|
// Check if cross signing is enabled and local secrets known
|
||||||
|
if (
|
||||||
|
crossSigningInfo.getOrNull() == null
|
||||||
|
|| (crossSigningInfo.getOrNull()?.isTrusted() == true
|
||||||
|
&& pInfo.getOrNull()?.allKnown().orFalse())
|
||||||
|
) {
|
||||||
|
// So 4S is not setup and we have local secrets,
|
||||||
|
return@combine BannerState.Setup(numberOfKeys = getNumberOfKeysToBackup())
|
||||||
|
}
|
||||||
|
BannerState.Hidden
|
||||||
|
|
||||||
|
}
|
||||||
|
.sample(1000) // we don't want to flicker or catch transient states
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
@ -135,7 +126,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
keyBackupPublishSubject.onNext(session.cryptoService().keysBackupService().state)
|
keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,7 +156,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStateChange(newState: KeysBackupState) {
|
override fun onStateChange(newState: KeysBackupState) {
|
||||||
keyBackupPublishSubject.onNext(session.cryptoService().keysBackupService().state)
|
keyBackupFlow.tryEmit(session.cryptoService().keysBackupService().state)
|
||||||
keysBackupState.value = newState
|
keysBackupState.value = newState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.app.features.workers.signout
|
package im.vector.app.features.workers.signout
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.airbnb.mvrx.ActivityViewModelContext
|
import com.airbnb.mvrx.ActivityViewModelContext
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
@ -35,6 +34,8 @@ import im.vector.app.core.platform.EmptyViewEvents
|
|||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
import im.vector.app.features.crypto.keys.KeysExporter
|
import im.vector.app.features.crypto.keys.KeysExporter
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||||
@ -42,7 +43,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_S
|
|||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.flow.flow
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
data class SignoutCheckViewState(
|
data class SignoutCheckViewState(
|
||||||
@ -97,7 +98,7 @@ class SignoutCheckViewModel @AssistedInject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.rx().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME))
|
session.flow().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME))
|
||||||
.map {
|
.map {
|
||||||
session.sharedSecretStorageService.isRecoverySetup()
|
session.sharedSecretStorageService.isRecoverySetup()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user