Merge pull request #7171 from vector-im/feature/ons/device_manager_security_sessions
[Device Manager] Unverified and inactive sessions list (PSG-698, PSG-696)
This commit is contained in:
commit
6c79aae3aa
1
changelog.d/7170.wip
Normal file
1
changelog.d/7170.wip
Normal file
@ -0,0 +1 @@
|
|||||||
|
[Device Manager] Unverified and inactive sessions list
|
@ -3244,6 +3244,7 @@
|
|||||||
<string name="device_manager_other_sessions_description_verified">Verified · Last activity %1$s</string>
|
<string name="device_manager_other_sessions_description_verified">Verified · Last activity %1$s</string>
|
||||||
<!-- Examples: Unverified · Last activity Yesterday at 6PM, Unverified · Last activity Aug 31 at 5:47PM -->
|
<!-- Examples: Unverified · Last activity Yesterday at 6PM, Unverified · Last activity Aug 31 at 5:47PM -->
|
||||||
<string name="device_manager_other_sessions_description_unverified">Unverified · Last activity %1$s</string>
|
<string name="device_manager_other_sessions_description_unverified">Unverified · Last activity %1$s</string>
|
||||||
|
<string name="device_manager_other_sessions_description_unverified_current_session">Unverified · Your current session</string>
|
||||||
<!-- Example: Inactive for 90+ days (Dec 25, 2021) -->
|
<!-- Example: Inactive for 90+ days (Dec 25, 2021) -->
|
||||||
<plurals name="device_manager_other_sessions_description_inactive">
|
<plurals name="device_manager_other_sessions_description_inactive">
|
||||||
<item quantity="one">Inactive for %1$d+ day (%2$s)</item>
|
<item quantity="one">Inactive for %1$d+ day (%2$s)</item>
|
||||||
|
@ -25,4 +25,5 @@ data class DeviceFullInfo(
|
|||||||
val cryptoDeviceInfo: CryptoDeviceInfo?,
|
val cryptoDeviceInfo: CryptoDeviceInfo?,
|
||||||
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel,
|
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel,
|
||||||
val isInactive: Boolean,
|
val isInactive: Boolean,
|
||||||
|
val isCurrentDevice: Boolean,
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,7 @@ class DevicesViewModel @AssistedInject constructor(
|
|||||||
.execute { async ->
|
.execute { async ->
|
||||||
if (async is Success) {
|
if (async is Success) {
|
||||||
val deviceFullInfoList = async.invoke()
|
val deviceFullInfoList = async.invoke()
|
||||||
val unverifiedSessionsCount = deviceFullInfoList.count { !it.cryptoDeviceInfo?.isVerified.orFalse() }
|
val unverifiedSessionsCount = deviceFullInfoList.count { !it.cryptoDeviceInfo?.trustLevel?.isCrossSigningVerified().orFalse() }
|
||||||
val inactiveSessionsCount = deviceFullInfoList.count { it.isInactive }
|
val inactiveSessionsCount = deviceFullInfoList.count { it.isInactive }
|
||||||
copy(
|
copy(
|
||||||
devices = async,
|
devices = async,
|
||||||
|
@ -71,7 +71,8 @@ class GetDeviceFullInfoListUseCase @Inject constructor(
|
|||||||
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
||||||
val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoDeviceInfo)
|
val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoDeviceInfo)
|
||||||
val isInactive = checkIfSessionIsInactiveUseCase.execute(deviceInfo.lastSeenTs ?: 0)
|
val isInactive = checkIfSessionIsInactiveUseCase.execute(deviceInfo.lastSeenTs ?: 0)
|
||||||
DeviceFullInfo(deviceInfo, cryptoDeviceInfo, roomEncryptionTrustLevel, isInactive)
|
val isCurrentDevice = currentSessionCrossSigningInfo.deviceId == cryptoDeviceInfo?.deviceId
|
||||||
|
DeviceFullInfo(deviceInfo, cryptoDeviceInfo, roomEncryptionTrustLevel, isInactive, isCurrentDevice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,11 @@ import im.vector.app.core.resources.DrawableProvider
|
|||||||
import im.vector.app.databinding.FragmentSettingsDevicesBinding
|
import im.vector.app.databinding.FragmentSettingsDevicesBinding
|
||||||
import im.vector.app.features.crypto.recover.SetupMode
|
import im.vector.app.features.crypto.recover.SetupMode
|
||||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||||
|
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||||
import im.vector.app.features.settings.devices.v2.list.NUMBER_OF_OTHER_DEVICES_TO_RENDER
|
import im.vector.app.features.settings.devices.v2.list.NUMBER_OF_OTHER_DEVICES_TO_RENDER
|
||||||
import im.vector.app.features.settings.devices.v2.list.OtherSessionsView
|
import im.vector.app.features.settings.devices.v2.list.OtherSessionsView
|
||||||
import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS
|
import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS
|
||||||
|
import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationView
|
||||||
import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationViewState
|
import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationViewState
|
||||||
import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
|
import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -83,6 +85,7 @@ class VectorSettingsDevicesFragment :
|
|||||||
initLearnMoreButtons()
|
initLearnMoreButtons()
|
||||||
initWaitingView()
|
initWaitingView()
|
||||||
initOtherSessionsView()
|
initOtherSessionsView()
|
||||||
|
initSecurityRecommendationsView()
|
||||||
observeViewEvents()
|
observeViewEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +127,29 @@ class VectorSettingsDevicesFragment :
|
|||||||
views.deviceListOtherSessions.callback = this
|
views.deviceListOtherSessions.callback = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initSecurityRecommendationsView() {
|
||||||
|
views.deviceListUnverifiedSessionsRecommendation.callback = object : SecurityRecommendationView.Callback {
|
||||||
|
override fun onViewAllClicked() {
|
||||||
|
viewNavigator.navigateToOtherSessions(
|
||||||
|
requireActivity(),
|
||||||
|
R.string.device_manager_header_section_security_recommendations_title,
|
||||||
|
DeviceManagerFilterType.UNVERIFIED,
|
||||||
|
excludeCurrentDevice = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
views.deviceListInactiveSessionsRecommendation.callback = object : SecurityRecommendationView.Callback {
|
||||||
|
override fun onViewAllClicked() {
|
||||||
|
viewNavigator.navigateToOtherSessions(
|
||||||
|
requireActivity(),
|
||||||
|
R.string.device_manager_header_section_security_recommendations_title,
|
||||||
|
DeviceManagerFilterType.INACTIVE,
|
||||||
|
excludeCurrentDevice = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
cleanUpLearnMoreButtonsListeners()
|
cleanUpLearnMoreButtonsListeners()
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
@ -262,6 +288,11 @@ class VectorSettingsDevicesFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewAllOtherSessionsClicked() {
|
override fun onViewAllOtherSessionsClicked() {
|
||||||
viewNavigator.navigateToOtherSessions(requireActivity())
|
viewNavigator.navigateToOtherSessions(
|
||||||
|
context = requireActivity(),
|
||||||
|
titleResourceId = R.string.device_manager_sessions_other_title,
|
||||||
|
defaultFilter = DeviceManagerFilterType.ALL_SESSIONS,
|
||||||
|
excludeCurrentDevice = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.features.settings.devices.v2
|
package im.vector.app.features.settings.devices.v2
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||||
import im.vector.app.features.settings.devices.v2.othersessions.OtherSessionsActivity
|
import im.vector.app.features.settings.devices.v2.othersessions.OtherSessionsActivity
|
||||||
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewActivity
|
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -27,7 +28,14 @@ class VectorSettingsDevicesViewNavigator @Inject constructor() {
|
|||||||
context.startActivity(SessionOverviewActivity.newIntent(context, deviceId))
|
context.startActivity(SessionOverviewActivity.newIntent(context, deviceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToOtherSessions(context: Context) {
|
fun navigateToOtherSessions(
|
||||||
context.startActivity(OtherSessionsActivity.newIntent(context))
|
context: Context,
|
||||||
|
titleResourceId: Int,
|
||||||
|
defaultFilter: DeviceManagerFilterType,
|
||||||
|
excludeCurrentDevice: Boolean,
|
||||||
|
) {
|
||||||
|
context.startActivity(
|
||||||
|
OtherSessionsActivity.newIntent(context, titleResourceId, defaultFilter, excludeCurrentDevice)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ class FilterDevicesUseCase @Inject constructor() {
|
|||||||
.filter {
|
.filter {
|
||||||
when (filterType) {
|
when (filterType) {
|
||||||
DeviceManagerFilterType.ALL_SESSIONS -> true
|
DeviceManagerFilterType.ALL_SESSIONS -> true
|
||||||
DeviceManagerFilterType.VERIFIED -> it.cryptoDeviceInfo?.isVerified.orFalse()
|
DeviceManagerFilterType.VERIFIED -> it.cryptoDeviceInfo?.trustLevel?.isCrossSigningVerified().orFalse()
|
||||||
DeviceManagerFilterType.UNVERIFIED -> !it.cryptoDeviceInfo?.isVerified.orFalse()
|
DeviceManagerFilterType.UNVERIFIED -> !it.cryptoDeviceInfo?.trustLevel?.isCrossSigningVerified().orFalse()
|
||||||
DeviceManagerFilterType.INACTIVE -> it.isInactive
|
DeviceManagerFilterType.INACTIVE -> it.isInactive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.list
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
@ -45,6 +46,10 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
|
|||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var sessionDescription: String? = null
|
var sessionDescription: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
@ColorInt
|
||||||
|
var sessionDescriptionColor: Int? = null
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var sessionDescriptionDrawable: Drawable? = null
|
var sessionDescriptionDrawable: Drawable? = null
|
||||||
|
|
||||||
@ -82,6 +87,9 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
|
|||||||
holder.otherSessionVerificationStatusImageView.render(roomEncryptionTrustLevel)
|
holder.otherSessionVerificationStatusImageView.render(roomEncryptionTrustLevel)
|
||||||
holder.otherSessionNameTextView.text = sessionName
|
holder.otherSessionNameTextView.text = sessionName
|
||||||
holder.otherSessionDescriptionTextView.text = sessionDescription
|
holder.otherSessionDescriptionTextView.text = sessionDescription
|
||||||
|
sessionDescriptionColor?.let {
|
||||||
|
holder.otherSessionDescriptionTextView.setTextColor(it)
|
||||||
|
}
|
||||||
holder.otherSessionDescriptionTextView.setCompoundDrawablesWithIntrinsicBounds(sessionDescriptionDrawable, null, null, null)
|
holder.otherSessionDescriptionTextView.setCompoundDrawablesWithIntrinsicBounds(sessionDescriptionDrawable, null, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,20 +53,14 @@ class OtherSessionsController @Inject constructor(
|
|||||||
data.forEach { device ->
|
data.forEach { device ->
|
||||||
val dateFormatKind = if (device.isInactive) DateFormatKind.TIMELINE_DAY_DIVIDER else DateFormatKind.DEFAULT_DATE_AND_TIME
|
val dateFormatKind = if (device.isInactive) DateFormatKind.TIMELINE_DAY_DIVIDER else DateFormatKind.DEFAULT_DATE_AND_TIME
|
||||||
val formattedLastActivityDate = host.dateFormatter.format(device.deviceInfo.lastSeenTs, dateFormatKind)
|
val formattedLastActivityDate = host.dateFormatter.format(device.deviceInfo.lastSeenTs, dateFormatKind)
|
||||||
val description = if (device.isInactive) {
|
val description = calculateDescription(device, formattedLastActivityDate)
|
||||||
stringProvider.getQuantityString(
|
val descriptionColor = if (device.isCurrentDevice) {
|
||||||
R.plurals.device_manager_other_sessions_description_inactive,
|
host.colorProvider.getColorFromAttribute(R.attr.colorError)
|
||||||
SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS,
|
|
||||||
SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS,
|
|
||||||
formattedLastActivityDate
|
|
||||||
)
|
|
||||||
} else if (device.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Trusted) {
|
|
||||||
stringProvider.getString(R.string.device_manager_other_sessions_description_verified, formattedLastActivityDate)
|
|
||||||
} else {
|
} else {
|
||||||
stringProvider.getString(R.string.device_manager_other_sessions_description_unverified, formattedLastActivityDate)
|
host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
|
||||||
}
|
}
|
||||||
val drawableColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
|
val drawableColor = host.colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
|
||||||
val descriptionDrawable = if (device.isInactive) drawableProvider.getDrawable(R.drawable.ic_inactive_sessions, drawableColor) else null
|
val descriptionDrawable = if (device.isInactive) host.drawableProvider.getDrawable(R.drawable.ic_inactive_sessions, drawableColor) else null
|
||||||
|
|
||||||
otherSessionItem {
|
otherSessionItem {
|
||||||
id(device.deviceInfo.deviceId)
|
id(device.deviceInfo.deviceId)
|
||||||
@ -75,10 +69,33 @@ class OtherSessionsController @Inject constructor(
|
|||||||
sessionName(device.deviceInfo.displayName)
|
sessionName(device.deviceInfo.displayName)
|
||||||
sessionDescription(description)
|
sessionDescription(description)
|
||||||
sessionDescriptionDrawable(descriptionDrawable)
|
sessionDescriptionDrawable(descriptionDrawable)
|
||||||
|
sessionDescriptionColor(descriptionColor)
|
||||||
stringProvider(this@OtherSessionsController.stringProvider)
|
stringProvider(this@OtherSessionsController.stringProvider)
|
||||||
clickListener { device.deviceInfo.deviceId?.let { host.callback?.onItemClicked(it) } }
|
clickListener { device.deviceInfo.deviceId?.let { host.callback?.onItemClicked(it) } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun calculateDescription(device: DeviceFullInfo, formattedLastActivityDate: String): String {
|
||||||
|
return when {
|
||||||
|
device.isInactive -> {
|
||||||
|
stringProvider.getQuantityString(
|
||||||
|
R.plurals.device_manager_other_sessions_description_inactive,
|
||||||
|
SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS,
|
||||||
|
SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS,
|
||||||
|
formattedLastActivityDate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
device.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Trusted -> {
|
||||||
|
stringProvider.getString(R.string.device_manager_other_sessions_description_verified, formattedLastActivityDate)
|
||||||
|
}
|
||||||
|
device.isCurrentDevice -> {
|
||||||
|
stringProvider.getString(R.string.device_manager_other_sessions_description_unverified_current_session)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
stringProvider.getString(R.string.device_manager_other_sessions_description_unverified, formattedLastActivityDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,12 @@ class SecurityRecommendationView @JvmOverloads constructor(
|
|||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onViewAllClicked()
|
||||||
|
}
|
||||||
|
|
||||||
private val views: ViewSecurityRecommendationBinding
|
private val views: ViewSecurityRecommendationBinding
|
||||||
|
var callback: Callback? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
inflate(context, R.layout.view_security_recommendation, this)
|
inflate(context, R.layout.view_security_recommendation, this)
|
||||||
@ -47,6 +52,10 @@ class SecurityRecommendationView @JvmOverloads constructor(
|
|||||||
setDescription(it)
|
setDescription(it)
|
||||||
setImage(it)
|
setImage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
views.recommendationViewAllButton.setOnClickListener {
|
||||||
|
callback?.onViewAllClicked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setTitle(typedArray: TypedArray) {
|
private fun setTitle(typedArray: TypedArray) {
|
||||||
@ -78,4 +87,9 @@ class SecurityRecommendationView @JvmOverloads constructor(
|
|||||||
setDescription(viewState.description)
|
setDescription(viewState.description)
|
||||||
setCount(viewState.sessionsCount)
|
setCount(viewState.sessionsCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
callback = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,12 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.airbnb.mvrx.Mavericks
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.core.extensions.addFragment
|
import im.vector.app.core.extensions.addFragment
|
||||||
import im.vector.app.core.platform.SimpleFragmentActivity
|
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||||
|
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class OtherSessionsActivity : SimpleFragmentActivity() {
|
class OtherSessionsActivity : SimpleFragmentActivity() {
|
||||||
@ -35,14 +38,23 @@ class OtherSessionsActivity : SimpleFragmentActivity() {
|
|||||||
if (isFirstCreation()) {
|
if (isFirstCreation()) {
|
||||||
addFragment(
|
addFragment(
|
||||||
container = views.container,
|
container = views.container,
|
||||||
fragmentClass = OtherSessionsFragment::class.java
|
fragmentClass = OtherSessionsFragment::class.java,
|
||||||
|
params = intent.getParcelableExtra(Mavericks.KEY_ARG)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newIntent(context: Context): Intent {
|
fun newIntent(
|
||||||
return Intent(context, OtherSessionsActivity::class.java)
|
context: Context,
|
||||||
|
@StringRes
|
||||||
|
titleResourceId: Int,
|
||||||
|
defaultFilter: DeviceManagerFilterType,
|
||||||
|
excludeCurrentDevice: Boolean,
|
||||||
|
): Intent {
|
||||||
|
return Intent(context, OtherSessionsActivity::class.java).apply {
|
||||||
|
putExtra(Mavericks.KEY_ARG, OtherSessionsArgs(titleResourceId, defaultFilter, excludeCurrentDevice))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.settings.devices.v2.othersessions
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class OtherSessionsArgs(
|
||||||
|
@StringRes
|
||||||
|
val titleResourceId: Int,
|
||||||
|
val defaultFilter: DeviceManagerFilterType,
|
||||||
|
val excludeCurrentDevice: Boolean,
|
||||||
|
) : Parcelable
|
@ -22,6 +22,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.args
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@ -46,6 +47,7 @@ class OtherSessionsFragment :
|
|||||||
OtherSessionsView.Callback {
|
OtherSessionsView.Callback {
|
||||||
|
|
||||||
private val viewModel: OtherSessionsViewModel by fragmentViewModel()
|
private val viewModel: OtherSessionsViewModel by fragmentViewModel()
|
||||||
|
private val args: OtherSessionsArgs by args()
|
||||||
|
|
||||||
@Inject lateinit var colorProvider: ColorProvider
|
@Inject lateinit var colorProvider: ColorProvider
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ class OtherSessionsFragment :
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setupToolbar(views.otherSessionsToolbar).allowBack()
|
setupToolbar(views.otherSessionsToolbar).setTitle(args.titleResourceId).allowBack()
|
||||||
observeViewEvents()
|
observeViewEvents()
|
||||||
initFilterView()
|
initFilterView()
|
||||||
}
|
}
|
||||||
@ -85,6 +87,10 @@ class OtherSessionsFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
views.deviceListOtherSessions.callback = this
|
views.deviceListOtherSessions.callback = this
|
||||||
|
|
||||||
|
if (args.defaultFilter != DeviceManagerFilterType.ALL_SESSIONS) {
|
||||||
|
viewModel.handle(OtherSessionsAction.FilterDevices(args.defaultFilter))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBottomSheetResult(resultCode: Int, data: Any?) {
|
override fun onBottomSheetResult(resultCode: Int, data: Any?) {
|
||||||
|
@ -30,7 +30,7 @@ import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
class OtherSessionsViewModel @AssistedInject constructor(
|
class OtherSessionsViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: OtherSessionsViewState,
|
@Assisted private val initialState: OtherSessionsViewState,
|
||||||
activeSessionHolder: ActiveSessionHolder,
|
activeSessionHolder: ActiveSessionHolder,
|
||||||
private val getDeviceFullInfoListUseCase: GetDeviceFullInfoListUseCase,
|
private val getDeviceFullInfoListUseCase: GetDeviceFullInfoListUseCase,
|
||||||
refreshDevicesUseCase: RefreshDevicesUseCase
|
refreshDevicesUseCase: RefreshDevicesUseCase
|
||||||
@ -55,7 +55,7 @@ class OtherSessionsViewModel @AssistedInject constructor(
|
|||||||
observeDevicesJob?.cancel()
|
observeDevicesJob?.cancel()
|
||||||
observeDevicesJob = getDeviceFullInfoListUseCase.execute(
|
observeDevicesJob = getDeviceFullInfoListUseCase.execute(
|
||||||
filterType = currentFilter,
|
filterType = currentFilter,
|
||||||
excludeCurrentDevice = true
|
excludeCurrentDevice = initialState.excludeCurrentDevice
|
||||||
)
|
)
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
|
@ -25,4 +25,8 @@ import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
|||||||
data class OtherSessionsViewState(
|
data class OtherSessionsViewState(
|
||||||
val devices: Async<List<DeviceFullInfo>> = Uninitialized,
|
val devices: Async<List<DeviceFullInfo>> = Uninitialized,
|
||||||
val currentFilter: DeviceManagerFilterType = DeviceManagerFilterType.ALL_SESSIONS,
|
val currentFilter: DeviceManagerFilterType = DeviceManagerFilterType.ALL_SESSIONS,
|
||||||
) : MavericksState
|
val excludeCurrentDevice: Boolean = false,
|
||||||
|
) : MavericksState {
|
||||||
|
|
||||||
|
constructor(args: OtherSessionsArgs) : this(excludeCurrentDevice = args.excludeCurrentDevice)
|
||||||
|
}
|
||||||
|
@ -48,11 +48,13 @@ class GetDeviceFullInfoUseCase @Inject constructor(
|
|||||||
val fullInfo = if (info != null && cryptoInfo != null) {
|
val fullInfo = if (info != null && cryptoInfo != null) {
|
||||||
val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoInfo)
|
val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoInfo)
|
||||||
val isInactive = checkIfSessionIsInactiveUseCase.execute(info.lastSeenTs ?: 0)
|
val isInactive = checkIfSessionIsInactiveUseCase.execute(info.lastSeenTs ?: 0)
|
||||||
|
val isCurrentDevice = currentSessionCrossSigningInfo.deviceId == cryptoInfo.deviceId
|
||||||
DeviceFullInfo(
|
DeviceFullInfo(
|
||||||
deviceInfo = info,
|
deviceInfo = info,
|
||||||
cryptoDeviceInfo = cryptoInfo,
|
cryptoDeviceInfo = cryptoInfo,
|
||||||
roomEncryptionTrustLevel = roomEncryptionTrustLevel,
|
roomEncryptionTrustLevel = roomEncryptionTrustLevel,
|
||||||
isInactive = isInactive
|
isInactive = isInactive,
|
||||||
|
isCurrentDevice = isCurrentDevice,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package im.vector.app.features.settings.devices.v2
|
package im.vector.app.features.settings.devices.v2
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.test.MvRxTestRule
|
import com.airbnb.mvrx.test.MvRxTestRule
|
||||||
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
|
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
|
||||||
@ -30,11 +31,16 @@ import io.mockk.coVerify
|
|||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.just
|
import io.mockk.just
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
import io.mockk.runs
|
import io.mockk.runs
|
||||||
|
import io.mockk.unmockkAll
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||||
|
|
||||||
@ -62,6 +68,17 @@ class DevicesViewModelTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
mockkStatic(SystemClock::class)
|
||||||
|
every { SystemClock.elapsedRealtime() } returns 1234
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkAll()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given the viewModel when initializing it then verification listener is added`() {
|
fun `given the viewModel when initializing it then verification listener is added`() {
|
||||||
// Given
|
// Given
|
||||||
@ -216,21 +233,23 @@ class DevicesViewModelTest {
|
|||||||
*/
|
*/
|
||||||
private fun givenDeviceFullInfoList(): List<DeviceFullInfo> {
|
private fun givenDeviceFullInfoList(): List<DeviceFullInfo> {
|
||||||
val verifiedCryptoDeviceInfo = mockk<CryptoDeviceInfo>()
|
val verifiedCryptoDeviceInfo = mockk<CryptoDeviceInfo>()
|
||||||
every { verifiedCryptoDeviceInfo.isVerified } returns true
|
every { verifiedCryptoDeviceInfo.trustLevel } returns DeviceTrustLevel(crossSigningVerified = true, locallyVerified = true)
|
||||||
val unverifiedCryptoDeviceInfo = mockk<CryptoDeviceInfo>()
|
val unverifiedCryptoDeviceInfo = mockk<CryptoDeviceInfo>()
|
||||||
every { unverifiedCryptoDeviceInfo.isVerified } returns false
|
every { unverifiedCryptoDeviceInfo.trustLevel } returns DeviceTrustLevel(crossSigningVerified = false, locallyVerified = false)
|
||||||
|
|
||||||
val deviceFullInfo1 = DeviceFullInfo(
|
val deviceFullInfo1 = DeviceFullInfo(
|
||||||
deviceInfo = mockk(),
|
deviceInfo = mockk(),
|
||||||
cryptoDeviceInfo = verifiedCryptoDeviceInfo,
|
cryptoDeviceInfo = verifiedCryptoDeviceInfo,
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
||||||
isInactive = false
|
isInactive = false,
|
||||||
|
isCurrentDevice = true
|
||||||
)
|
)
|
||||||
val deviceFullInfo2 = DeviceFullInfo(
|
val deviceFullInfo2 = DeviceFullInfo(
|
||||||
deviceInfo = mockk(),
|
deviceInfo = mockk(),
|
||||||
cryptoDeviceInfo = unverifiedCryptoDeviceInfo,
|
cryptoDeviceInfo = unverifiedCryptoDeviceInfo,
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
||||||
isInactive = true
|
isInactive = true,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
val deviceFullInfoList = listOf(deviceFullInfo1, deviceFullInfo2)
|
val deviceFullInfoList = listOf(deviceFullInfo1, deviceFullInfo2)
|
||||||
val deviceFullInfoListFlow = flowOf(deviceFullInfoList)
|
val deviceFullInfoListFlow = flowOf(deviceFullInfoList)
|
||||||
|
@ -109,19 +109,22 @@ class GetDeviceFullInfoListUseCaseTest {
|
|||||||
deviceInfo = deviceInfo1,
|
deviceInfo = deviceInfo1,
|
||||||
cryptoDeviceInfo = cryptoDeviceInfo1,
|
cryptoDeviceInfo = cryptoDeviceInfo1,
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
||||||
isInactive = true
|
isInactive = true,
|
||||||
|
isCurrentDevice = true
|
||||||
)
|
)
|
||||||
val expectedResult2 = DeviceFullInfo(
|
val expectedResult2 = DeviceFullInfo(
|
||||||
deviceInfo = deviceInfo2,
|
deviceInfo = deviceInfo2,
|
||||||
cryptoDeviceInfo = cryptoDeviceInfo2,
|
cryptoDeviceInfo = cryptoDeviceInfo2,
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
||||||
isInactive = false
|
isInactive = false,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
val expectedResult3 = DeviceFullInfo(
|
val expectedResult3 = DeviceFullInfo(
|
||||||
deviceInfo = deviceInfo3,
|
deviceInfo = deviceInfo3,
|
||||||
cryptoDeviceInfo = cryptoDeviceInfo3,
|
cryptoDeviceInfo = cryptoDeviceInfo3,
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
||||||
isInactive = false
|
isInactive = false,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
val expectedResult = listOf(expectedResult3, expectedResult2, expectedResult1)
|
val expectedResult = listOf(expectedResult3, expectedResult2, expectedResult1)
|
||||||
every { filterDevicesUseCase.execute(any(), any()) } returns expectedResult
|
every { filterDevicesUseCase.execute(any(), any()) } returns expectedResult
|
||||||
@ -163,6 +166,7 @@ class GetDeviceFullInfoListUseCaseTest {
|
|||||||
private fun givenCurrentSessionCrossSigningInfo(): CurrentSessionCrossSigningInfo {
|
private fun givenCurrentSessionCrossSigningInfo(): CurrentSessionCrossSigningInfo {
|
||||||
val currentSessionCrossSigningInfo = mockk<CurrentSessionCrossSigningInfo>()
|
val currentSessionCrossSigningInfo = mockk<CurrentSessionCrossSigningInfo>()
|
||||||
every { getCurrentSessionCrossSigningInfoUseCase.execute() } returns flowOf(currentSessionCrossSigningInfo)
|
every { getCurrentSessionCrossSigningInfoUseCase.execute() } returns flowOf(currentSessionCrossSigningInfo)
|
||||||
|
every { currentSessionCrossSigningInfo.deviceId } returns A_DEVICE_ID_1
|
||||||
return currentSessionCrossSigningInfo
|
return currentSessionCrossSigningInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.features.settings.devices.v2
|
package im.vector.app.features.settings.devices.v2
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||||
import im.vector.app.features.settings.devices.v2.othersessions.OtherSessionsActivity
|
import im.vector.app.features.settings.devices.v2.othersessions.OtherSessionsActivity
|
||||||
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewActivity
|
import im.vector.app.features.settings.devices.v2.overview.SessionOverviewActivity
|
||||||
import im.vector.app.test.fakes.FakeContext
|
import im.vector.app.test.fakes.FakeContext
|
||||||
@ -30,6 +31,8 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
private const val A_SESSION_ID = "session_id"
|
private const val A_SESSION_ID = "session_id"
|
||||||
|
private const val A_TITLE_RESOURCE_ID = 1234
|
||||||
|
private val A_DEFAULT_FILTER = DeviceManagerFilterType.INACTIVE
|
||||||
|
|
||||||
class VectorSettingsDevicesViewNavigatorTest {
|
class VectorSettingsDevicesViewNavigatorTest {
|
||||||
|
|
||||||
@ -61,10 +64,10 @@ class VectorSettingsDevicesViewNavigatorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given an intent when navigating to other sessions list then it starts the correct activity`() {
|
fun `given an intent when navigating to other sessions list then it starts the correct activity`() {
|
||||||
val intent = givenIntentForOtherSessions()
|
val intent = givenIntentForOtherSessions(A_TITLE_RESOURCE_ID, A_DEFAULT_FILTER, true)
|
||||||
context.givenStartActivity(intent)
|
context.givenStartActivity(intent)
|
||||||
|
|
||||||
vectorSettingsDevicesViewNavigator.navigateToOtherSessions(context.instance)
|
vectorSettingsDevicesViewNavigator.navigateToOtherSessions(context.instance, A_TITLE_RESOURCE_ID, A_DEFAULT_FILTER, true)
|
||||||
|
|
||||||
verify {
|
verify {
|
||||||
context.instance.startActivity(intent)
|
context.instance.startActivity(intent)
|
||||||
@ -77,9 +80,9 @@ class VectorSettingsDevicesViewNavigatorTest {
|
|||||||
return intent
|
return intent
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun givenIntentForOtherSessions(): Intent {
|
private fun givenIntentForOtherSessions(titleResourceId: Int, defaultFilter: DeviceManagerFilterType, excludeCurrentDevice: Boolean): Intent {
|
||||||
val intent = mockk<Intent>()
|
val intent = mockk<Intent>()
|
||||||
every { OtherSessionsActivity.newIntent(context.instance) } returns intent
|
every { OtherSessionsActivity.newIntent(context.instance, titleResourceId, defaultFilter, excludeCurrentDevice) } returns intent
|
||||||
return intent
|
return intent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,8 @@ private val activeVerifiedDevice = DeviceFullInfo(
|
|||||||
trustLevel = DeviceTrustLevel(crossSigningVerified = true, locallyVerified = true)
|
trustLevel = DeviceTrustLevel(crossSigningVerified = true, locallyVerified = true)
|
||||||
),
|
),
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
||||||
isInactive = false
|
isInactive = false,
|
||||||
|
isCurrentDevice = true
|
||||||
)
|
)
|
||||||
private val inactiveVerifiedDevice = DeviceFullInfo(
|
private val inactiveVerifiedDevice = DeviceFullInfo(
|
||||||
deviceInfo = DeviceInfo(deviceId = "INACTIVE_VERIFIED_DEVICE"),
|
deviceInfo = DeviceInfo(deviceId = "INACTIVE_VERIFIED_DEVICE"),
|
||||||
@ -43,7 +44,8 @@ private val inactiveVerifiedDevice = DeviceFullInfo(
|
|||||||
trustLevel = DeviceTrustLevel(crossSigningVerified = true, locallyVerified = true)
|
trustLevel = DeviceTrustLevel(crossSigningVerified = true, locallyVerified = true)
|
||||||
),
|
),
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Trusted,
|
||||||
isInactive = true
|
isInactive = true,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
private val activeUnverifiedDevice = DeviceFullInfo(
|
private val activeUnverifiedDevice = DeviceFullInfo(
|
||||||
deviceInfo = DeviceInfo(deviceId = "ACTIVE_UNVERIFIED_DEVICE"),
|
deviceInfo = DeviceInfo(deviceId = "ACTIVE_UNVERIFIED_DEVICE"),
|
||||||
@ -53,7 +55,8 @@ private val activeUnverifiedDevice = DeviceFullInfo(
|
|||||||
trustLevel = DeviceTrustLevel(crossSigningVerified = false, locallyVerified = false)
|
trustLevel = DeviceTrustLevel(crossSigningVerified = false, locallyVerified = false)
|
||||||
),
|
),
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
||||||
isInactive = false
|
isInactive = false,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
private val inactiveUnverifiedDevice = DeviceFullInfo(
|
private val inactiveUnverifiedDevice = DeviceFullInfo(
|
||||||
deviceInfo = DeviceInfo(deviceId = "INACTIVE_UNVERIFIED_DEVICE"),
|
deviceInfo = DeviceInfo(deviceId = "INACTIVE_UNVERIFIED_DEVICE"),
|
||||||
@ -63,7 +66,8 @@ private val inactiveUnverifiedDevice = DeviceFullInfo(
|
|||||||
trustLevel = DeviceTrustLevel(crossSigningVerified = false, locallyVerified = false)
|
trustLevel = DeviceTrustLevel(crossSigningVerified = false, locallyVerified = false)
|
||||||
),
|
),
|
||||||
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
roomEncryptionTrustLevel = RoomEncryptionTrustLevel.Warning,
|
||||||
isInactive = true
|
isInactive = true,
|
||||||
|
isCurrentDevice = false
|
||||||
)
|
)
|
||||||
|
|
||||||
private val devices = listOf(
|
private val devices = listOf(
|
||||||
|
@ -85,6 +85,7 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData.givenAsFlow()
|
fakeActiveSessionHolder.fakeSession.fakeCryptoService.cryptoDeviceInfoWithIdLiveData.givenAsFlow()
|
||||||
val trustLevel = givenTrustLevel(currentSessionCrossSigningInfo, cryptoDeviceInfo)
|
val trustLevel = givenTrustLevel(currentSessionCrossSigningInfo, cryptoDeviceInfo)
|
||||||
val isInactive = false
|
val isInactive = false
|
||||||
|
val isCurrentDevice = true
|
||||||
every { checkIfSessionIsInactiveUseCase.execute(any()) } returns isInactive
|
every { checkIfSessionIsInactiveUseCase.execute(any()) } returns isInactive
|
||||||
|
|
||||||
// When
|
// When
|
||||||
@ -96,6 +97,7 @@ class GetDeviceFullInfoUseCaseTest {
|
|||||||
cryptoDeviceInfo = cryptoDeviceInfo,
|
cryptoDeviceInfo = cryptoDeviceInfo,
|
||||||
roomEncryptionTrustLevel = trustLevel,
|
roomEncryptionTrustLevel = trustLevel,
|
||||||
isInactive = isInactive,
|
isInactive = isInactive,
|
||||||
|
isCurrentDevice = isCurrentDevice
|
||||||
)
|
)
|
||||||
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
verify { fakeActiveSessionHolder.instance.getSafeActiveSession() }
|
||||||
verify { getCurrentSessionCrossSigningInfoUseCase.execute() }
|
verify { getCurrentSessionCrossSigningInfoUseCase.execute() }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user