From 42b47c25aae9fdc0e7650a3c5703f14fd5f4c3e1 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 27 Apr 2020 10:07:28 +0200 Subject: [PATCH] Remember ignored unknown sessions --- .../riotx/features/home/HomeDetailFragment.kt | 9 ++- .../UnknwonDeviceDetectorSharedViewModel.kt | 55 ++++++++++++++++--- .../features/settings/VectorPreferences.kt | 15 +++++ 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt index 564b030081..76d0f8a2e2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt @@ -1,4 +1,3 @@ - /* * Copyright 2019 New Vector Ltd * @@ -61,7 +60,7 @@ class HomeDetailFragment @Inject constructor( private val unreadCounterBadgeViews = arrayListOf() private val viewModel: HomeDetailViewModel by fragmentViewModel() - private val unknownDeviceDetectorSharedViewModel : UnknownDeviceDetectorSharedViewModel by activityViewModel() + private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() private lateinit var sharedActionViewModel: HomeSharedActionViewModel @@ -112,7 +111,11 @@ class HomeDetailFragment @Inject constructor( ?.navigator ?.requestSessionVerification(requireContext(), newest.deviceId ?: "") } - dismissedAction = Runnable {} + dismissedAction = Runnable { + unknownDeviceDetectorSharedViewModel.handle( + UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(newest.deviceId ?: "") + ) + } } ) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/UnknwonDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/UnknwonDeviceDetectorSharedViewModel.kt index 6d10c53493..12485500c1 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/UnknwonDeviceDetectorSharedViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/UnknwonDeviceDetectorSharedViewModel.kt @@ -19,6 +19,7 @@ package im.vector.riotx.features.home import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext import im.vector.matrix.android.api.session.Session @@ -30,9 +31,11 @@ import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.matrix.rx.rx import im.vector.matrix.rx.singleBuilder import im.vector.riotx.core.di.HasScreenInjector -import im.vector.riotx.core.platform.EmptyAction import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel +import im.vector.riotx.core.platform.VectorViewModelAction +import im.vector.riotx.features.settings.VectorPreferences +import timber.log.Timber import java.util.concurrent.TimeUnit data class UnknownDevicesState( @@ -40,16 +43,31 @@ data class UnknownDevicesState( val canCrossSign: Boolean = false ) : MvRxState -class UnknownDeviceDetectorSharedViewModel(session: Session, initialState: UnknownDevicesState) - : VectorViewModel(initialState) { +class UnknownDeviceDetectorSharedViewModel( + session: Session, + private val vectorPreferences: VectorPreferences, + initialState: UnknownDevicesState) + : VectorViewModel(initialState) { + + sealed class Action : VectorViewModelAction { + data class IgnoreDevice(val deviceId: String) : Action() + } + + val ignoredDeviceList = ArrayList() init { + + ignoredDeviceList.addAll( + vectorPreferences.getUnknownDeviceDismissedList().also { + Timber.v("## Detector - Remembered ignored list $it") + } + ) session.rx().liveUserCryptoDevices(session.myUserId) .debounce(600, TimeUnit.MILLISECONDS) .distinct() .switchMap { deviceList -> - // Timber.v("## Detector - ============================") -// Timber.v("## Detector - Crypto device update ${deviceList.map { "${it.deviceId} : ${it.isVerified}" }}") + Timber.v("## Detector - ============================") + Timber.v("## Detector - Crypto device update ${deviceList.map { "${it.deviceId} : ${it.isVerified}" }}") singleBuilder { session.cryptoService().getDevicesList(it) NoOpCancellable @@ -59,10 +77,13 @@ class UnknownDeviceDetectorSharedViewModel(session: Session, initialState: Unkno deviceList.firstOrNull { info.deviceId == it.deviceId }?.let { !it.isVerified } ?: false - }?.sortedByDescending { it.lastSeenTs } + } + ?.sortedByDescending { it.lastSeenTs } ?.map { session.getUser(it.user_id ?: "")?.toMatrixItem() to it - } ?: emptyList() + } + ?.filter { !ignoredDeviceList.contains(it.second.deviceId) } + ?: emptyList() } .toObservable() } @@ -76,12 +97,28 @@ class UnknownDeviceDetectorSharedViewModel(session: Session, initialState: Unkno } } - override fun handle(action: EmptyAction) {} + override fun handle(action: Action) { + when (action) { + is Action.IgnoreDevice -> { + // local echo + withState { state -> + state.unknownSessions.invoke()?.let { + val updated = it.filter { it.second.deviceId != action.deviceId } + setState { + copy(unknownSessions = Success(updated)) + } + } + } + ignoredDeviceList.add(action.deviceId) + vectorPreferences.storeUnknownDeviceDismissedList(ignoredDeviceList) + } + } + } companion object : MvRxViewModelFactory { override fun create(viewModelContext: ViewModelContext, state: UnknownDevicesState): UnknownDeviceDetectorSharedViewModel? { val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() - return UnknownDeviceDetectorSharedViewModel(session, state) + return UnknownDeviceDetectorSharedViewModel(session, VectorPreferences(viewModelContext.activity()), state) } } } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index e765f961dd..beda003065 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -24,6 +24,7 @@ import android.provider.MediaStore import androidx.core.content.edit import androidx.preference.PreferenceManager import com.squareup.seismic.ShakeDetector +import im.vector.matrix.android.api.extensions.tryThis import im.vector.riotx.BuildConfig import im.vector.riotx.R import im.vector.riotx.features.homeserver.ServerUrlsRepository @@ -166,6 +167,8 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val MEDIA_SAVING_1_MONTH = 2 private const val MEDIA_SAVING_FOREVER = 3 + private const val SETTINGS_UNKNOWN_DEVICE_DISMISSED_LIST = "SETTINGS_UNKNWON_DEVICE_DISMISSED_LIST" + // some preferences keys must be kept after a logout private val mKeysToKeepAfterLogout = listOf( SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY, @@ -364,6 +367,18 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_PLAY_SHUTTER_SOUND_KEY, true) } + fun storeUnknownDeviceDismissedList(deviceIds: List) { + defaultPrefs.edit(true) { + putStringSet(SETTINGS_UNKNOWN_DEVICE_DISMISSED_LIST, deviceIds.toSet()) + } + } + + fun getUnknownDeviceDismissedList(): List { + return tryThis { + defaultPrefs.getStringSet(SETTINGS_UNKNOWN_DEVICE_DISMISSED_LIST, null)?.toList() + } ?: emptyList() + } + /** * Update the notification ringtone *