From b6f345aec2ed862f30f04005f3a162d99c5fb644 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 10:18:30 +0200 Subject: [PATCH 01/10] Format --- .../android/sdk/api/session/room/timeline/TimelineSettings.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt index 6548453c8a..b45f3ecb71 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineSettings.kt @@ -31,7 +31,8 @@ data class TimelineSettings( /** * The root thread eventId if this is a thread timeline, or null if this is NOT a thread timeline */ - val rootThreadEventId: String? = null) { + val rootThreadEventId: String? = null, +) { /** * Returns true if this is a thread timeline or false otherwise From ff28cb434937480b63c32ee11cc18854de441fe1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 10:41:09 +0200 Subject: [PATCH 02/10] Add TODO --- .../sdk/api/session/room/timeline/TimelineEventFilters.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt index 4415c8e4b3..a35a291d9b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEventFilters.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.api.session.room.timeline +// TODO Move to internal, strange? data class TimelineEventFilters( /** * A flag to filter edit events From 6ed1516d90dc7567fa69db2509739f71f5ff9326 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 10:57:04 +0200 Subject: [PATCH 03/10] Delete messages from just ignored users from our database (#1899) --- .../sync/handler/UserAccountDataSyncHandler.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt index 7f80486c70..c7d7dce17a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt @@ -39,6 +39,8 @@ import org.matrix.android.sdk.internal.database.model.IgnoredUserEntity import org.matrix.android.sdk.internal.database.model.PushRulesEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields +import org.matrix.android.sdk.internal.database.model.TimelineEventEntity +import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity import org.matrix.android.sdk.internal.database.model.UserAccountDataEntityFields import org.matrix.android.sdk.internal.database.model.deleteOnCascade @@ -189,7 +191,19 @@ internal class UserAccountDataSyncHandler @Inject constructor( .deleteAllFromRealm() // And save the new received list userIds.forEach { realm.createObject(IgnoredUserEntity::class.java).apply { userId = it } } - // TODO If not initial sync, we should execute a init sync + + // Delete all the TimelineEvents for all the ignored users + // See https://spec.matrix.org/latest/client-server-api/#client-behaviour-22 : + // "Once ignored, the client will no longer receive events sent by that user, with the exception of state events" + // So just delete all non-state events from our local storage. + realm.where(TimelineEventEntity::class.java) + .`in`(TimelineEventEntityFields.ROOT.SENDER, userIds.toTypedArray()) + .isNull(TimelineEventEntityFields.ROOT.STATE_KEY) + .findAll() + .also { Timber.d("Deleting ${it.size} TimelineEventEntity from ignored users") } + .forEach { + it.deleteOnCascade(true) + } } private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) { From 6b9f2965da790a887e5d45a1085d1ac9c4c00a7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 12:07:28 +0200 Subject: [PATCH 04/10] Request an initial sync when a user is unignored (#1899) --- .../android/sdk/api/failure/GlobalError.kt | 5 +++ .../api/failure/InitialSyncRequestReason.kt | 27 ++++++++++++++++ .../matrix/android/sdk/api/session/Session.kt | 1 + .../handler/UserAccountDataSyncHandler.kt | 32 ++++++++++++++++--- .../app/core/platform/VectorBaseActivity.kt | 20 ++++++++++++ vector/src/main/res/values/strings.xml | 3 ++ 6 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt index b5165b6687..5b4896f95f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt @@ -23,5 +23,10 @@ sealed class GlobalError { data class InvalidToken(val softLogout: Boolean) : GlobalError() data class ConsentNotGivenError(val consentUri: String) : GlobalError() data class CertificateError(val fingerprint: Fingerprint) : GlobalError() + + /** + * The SDK requires the app (which should request the user) to perform an initial sync. + */ + data class InitialSyncRequest(val reason: InitialSyncRequestReason) : GlobalError() object ExpiredAccount : GlobalError() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt new file mode 100644 index 0000000000..5717f41f43 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt @@ -0,0 +1,27 @@ +/* + * 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 org.matrix.android.sdk.api.failure + +/** + * This enum provide the reason why the SDK request an initial sync to the application + */ +enum class InitialSyncRequestReason { + /** + * The list of ignored users has changed, and at least one user who was ignored is not ignored anymore + */ + IGNORED_USERS_LIST_CHANGE, +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index be924e2063..2ad0ae9e0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -298,6 +298,7 @@ interface Session : * Possible cases: * - The access token is not valid anymore, * - a M_CONSENT_NOT_GIVEN error has been received from the homeserver + * See [GlobalError] for all the possible cases */ fun onGlobalError(session: Session, globalError: GlobalError) = Unit } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt index c7d7dce17a..ce827c2311 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/UserAccountDataSyncHandler.kt @@ -20,6 +20,8 @@ import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmList import io.realm.kotlin.where +import org.matrix.android.sdk.api.failure.GlobalError +import org.matrix.android.sdk.api.failure.InitialSyncRequestReason import org.matrix.android.sdk.api.pushrules.RuleScope import org.matrix.android.sdk.api.pushrules.RuleSetKey import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse @@ -31,6 +33,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.sync.model.InvitedRoomSync import org.matrix.android.sdk.api.session.sync.model.UserAccountDataSync +import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.mapper.PushRulesMapper import org.matrix.android.sdk.internal.database.mapper.asDomain @@ -48,7 +51,10 @@ import org.matrix.android.sdk.internal.database.query.getDirectRooms import org.matrix.android.sdk.internal.database.query.getOrCreate import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.session.SessionListeners +import org.matrix.android.sdk.internal.session.dispatchTo import org.matrix.android.sdk.internal.session.room.RoomAvatarResolver import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper @@ -67,7 +73,10 @@ internal class UserAccountDataSyncHandler @Inject constructor( private val directChatsHelper: DirectChatsHelper, private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val roomAvatarResolver: RoomAvatarResolver, - private val roomDisplayNameResolver: RoomDisplayNameResolver + private val roomDisplayNameResolver: RoomDisplayNameResolver, + @SessionId private val sessionId: String, + private val sessionManager: SessionManager, + private val sessionListeners: SessionListeners ) { fun handle(realm: Realm, accountData: UserAccountDataSync?) { @@ -186,9 +195,10 @@ internal class UserAccountDataSyncHandler @Inject constructor( private fun handleIgnoredUsers(realm: Realm, event: UserAccountDataEvent) { val userIds = event.content.toModel()?.ignoredUsers?.keys ?: return - realm.where(IgnoredUserEntity::class.java) - .findAll() - .deleteAllFromRealm() + val currentIgnoredUsers = realm.where(IgnoredUserEntity::class.java).findAll() + val currentIgnoredUserIds = currentIgnoredUsers.map { it.userId } + // Delete the previous list + currentIgnoredUsers.deleteAllFromRealm() // And save the new received list userIds.forEach { realm.createObject(IgnoredUserEntity::class.java).apply { userId = it } } @@ -204,6 +214,20 @@ internal class UserAccountDataSyncHandler @Inject constructor( .forEach { it.deleteOnCascade(true) } + + // Handle the case when some users are unignored from another session + val mustRefreshCache = currentIgnoredUserIds.any { currentIgnoredUserId -> currentIgnoredUserId !in userIds } + if (mustRefreshCache) { + Timber.d("A user has been unignored from another session, an initial sync should be performed") + dispatchMustRefresh() + } + } + + private fun dispatchMustRefresh() { + val session = sessionManager.getSessionComponent(sessionId)?.session() + session.dispatchTo(sessionListeners) { safeSession, listener -> + listener.onGlobalError(safeSession, GlobalError.InitialSyncRequest(InitialSyncRequestReason.IGNORED_USERS_LIST_CHANGE)) + } } private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) { diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt index 4796022856..febcfc5ef2 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt @@ -46,6 +46,7 @@ import androidx.viewbinding.ViewBinding import com.airbnb.mvrx.MavericksView import com.bumptech.glide.util.Util import com.google.android.material.appbar.MaterialToolbar +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.EntryPointAccessors import im.vector.app.BuildConfig @@ -86,6 +87,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.failure.GlobalError +import org.matrix.android.sdk.api.failure.InitialSyncRequestReason import reactivecircus.flowbinding.android.view.clicks import timber.log.Timber import javax.inject.Inject @@ -266,9 +268,27 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver is GlobalError.CertificateError -> handleCertificateError(globalError) GlobalError.ExpiredAccount -> Unit // TODO Handle account expiration + is GlobalError.InitialSyncRequest -> handleInitialSyncRequest(globalError) } } + private fun handleInitialSyncRequest(initialSyncRequest: GlobalError.InitialSyncRequest) { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.initial_sync_request_title) + .setMessage( + getString(R.string.initial_sync_request_content, getString( + when (initialSyncRequest.reason) { + InitialSyncRequestReason.IGNORED_USERS_LIST_CHANGE -> R.string.initial_sync_request_reason_unignored_users + } + )) + ) + .setPositiveButton(R.string.ok) { _, _ -> + MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) + } + .setNegativeButton(R.string.later, null) + .show() + } + private fun handleCertificateError(certificateError: GlobalError.CertificateError) { singletonEntryPoint() .unrecognizedCertificateDialog() diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index ffd4333071..89ed125afd 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -176,6 +176,9 @@ Initial sync:\nImporting communities Initial sync:\nImporting account data + Initial sync request + ${app_name} needs to perform a clear cache to be up to date, for the following reason:\n%s\n\nNote that this action will restart the app and it may take some time. + - Some users have been unignored Message sent Sending messageā€¦ From a39516534ac5c8b5d852902c0d6407496194d80c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 12:43:57 +0200 Subject: [PATCH 05/10] Initial sync dialog will now come later. It allows to unignore several user without performing an initial sync each time. --- .../app/features/home/room/detail/TimelineFragment.kt | 10 ++-------- .../roommemberprofile/RoomMemberProfileFragment.kt | 11 +---------- .../roommemberprofile/RoomMemberProfileViewEvents.kt | 2 +- .../roommemberprofile/RoomMemberProfileViewModel.kt | 2 +- .../ignored/VectorSettingsIgnoredUsersFragment.kt | 7 +------ vector/src/main/res/values/strings.xml | 4 ++-- 6 files changed, 8 insertions(+), 28 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 32f0e46eac..4603793bd5 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -119,8 +119,6 @@ import im.vector.app.core.utils.startInstallFromSourceIntent import im.vector.app.core.utils.toast import im.vector.app.databinding.DialogReportContentBinding import im.vector.app.databinding.FragmentTimelineBinding -import im.vector.app.features.MainActivity -import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.extensions.toAnalyticsInteraction import im.vector.app.features.analytics.plan.Interaction import im.vector.app.features.analytics.plan.MobileScreen @@ -1730,14 +1728,10 @@ class TimelineFragment @Inject constructor( dismissLoadingDialog() views.composerLayout.setTextIfDifferent("") when (parsedCommand) { - is ParsedCommand.SetMarkdown -> { + is ParsedCommand.SetMarkdown -> { showSnackWithMessage(getString(if (parsedCommand.enable) R.string.markdown_has_been_enabled else R.string.markdown_has_been_disabled)) } - is ParsedCommand.UnignoreUser -> { - // A user has been un-ignored, perform a initial sync - MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) - } - else -> Unit + else -> Unit } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 5fee420b21..760bbe9353 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -47,8 +47,6 @@ import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.DialogShareQrCodeBinding import im.vector.app.databinding.FragmentMatrixProfileBinding import im.vector.app.databinding.ViewStubRoomMemberProfileHeaderBinding -import im.vector.app.features.MainActivity -import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.displayname.getBestName @@ -133,20 +131,13 @@ class RoomMemberProfileFragment @Inject constructor( is RoomMemberProfileViewEvents.OnKickActionSuccess -> Unit is RoomMemberProfileViewEvents.OnSetPowerLevelSuccess -> Unit is RoomMemberProfileViewEvents.OnBanActionSuccess -> Unit - is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> handleOnIgnoreActionSuccess(it) + is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit is RoomMemberProfileViewEvents.OnInviteActionSuccess -> Unit } } setupLongClicks() } - private fun handleOnIgnoreActionSuccess(action: RoomMemberProfileViewEvents.OnIgnoreActionSuccess) { - if (action.shouldPerformInitialSync) { - // A user has been un-ignored, perform a initial sync - MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) - } - } - private fun setupLongClicks() { headerViews.memberProfileNameView.copyOnLongClick() headerViews.memberProfileIdView.copyOnLongClick() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt index 1857f5cdc4..efe23eeff0 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt @@ -25,7 +25,7 @@ sealed class RoomMemberProfileViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : RoomMemberProfileViewEvents() data class Failure(val throwable: Throwable) : RoomMemberProfileViewEvents() - data class OnIgnoreActionSuccess(val shouldPerformInitialSync: Boolean) : RoomMemberProfileViewEvents() + object OnIgnoreActionSuccess : RoomMemberProfileViewEvents() object OnSetPowerLevelSuccess : RoomMemberProfileViewEvents() object OnInviteActionSuccess : RoomMemberProfileViewEvents() object OnKickActionSuccess : RoomMemberProfileViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index addc2c71ef..4bcf9ef55d 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -390,7 +390,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor( } else { session.ignoreUserIds(listOf(state.userId)) } - RoomMemberProfileViewEvents.OnIgnoreActionSuccess(isIgnored) + RoomMemberProfileViewEvents.OnIgnoreActionSuccess } catch (failure: Throwable) { RoomMemberProfileViewEvents.Failure(failure) } diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index 66fa690b82..2ae7ba0a8d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -62,16 +62,11 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( when (it) { is IgnoredUsersViewEvents.Loading -> showLoading(it.message) is IgnoredUsersViewEvents.Failure -> showFailure(it.throwable) - IgnoredUsersViewEvents.Success -> handleSuccess() + IgnoredUsersViewEvents.Success -> Unit } } } - private fun handleSuccess() { - // A user has been un-ignored, perform a initial sync - MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) - } - override fun onDestroyView() { ignoredUsersController.callback = null views.genericRecyclerView.cleanup() diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 89ed125afd..1a9634ff90 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -637,7 +637,7 @@ Ignore Unignore user - Unignoring this user will show all messages from them again.\n\nNote that this action will restart the app and it may take some time. + Unignoring this user will show all messages from them again. Unignore Cancel invite @@ -1035,7 +1035,7 @@ Failed to update password The password is not valid Your password has been updated - Show all messages from %s?\n\nNote that this action will restart the app and it may take some time. + Show all messages from %s? Emails and phone numbers Manage emails and phone numbers linked to your Matrix account From cdcf57659fcb58071941cbaf9f79ca345ad54fda Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 12:53:40 +0200 Subject: [PATCH 06/10] Do not update the cache manually, else the initial sync request will not be triggered. --- .../sdk/internal/session/user/UserModule.kt | 5 -- .../user/accountdata/SaveIgnoredUsersTask.kt | 47 ------------------- .../accountdata/UpdateIgnoredUserIdsTask.kt | 4 -- 3 files changed, 56 deletions(-) delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt index 4dfc7586ae..c205c4f1c6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserModule.kt @@ -21,9 +21,7 @@ import dagger.Module import dagger.Provides import org.matrix.android.sdk.api.session.user.UserService import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.session.user.accountdata.DefaultSaveIgnoredUsersTask import org.matrix.android.sdk.internal.session.user.accountdata.DefaultUpdateIgnoredUserIdsTask -import org.matrix.android.sdk.internal.session.user.accountdata.SaveIgnoredUsersTask import org.matrix.android.sdk.internal.session.user.accountdata.UpdateIgnoredUserIdsTask import org.matrix.android.sdk.internal.session.user.model.DefaultSearchUserTask import org.matrix.android.sdk.internal.session.user.model.SearchUserTask @@ -48,9 +46,6 @@ internal abstract class UserModule { @Binds abstract fun bindSearchUserTask(task: DefaultSearchUserTask): SearchUserTask - @Binds - abstract fun bindSaveIgnoredUsersTask(task: DefaultSaveIgnoredUsersTask): SaveIgnoredUsersTask - @Binds abstract fun bindUpdateIgnoredUserIdsTask(task: DefaultUpdateIgnoredUserIdsTask): UpdateIgnoredUserIdsTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt deleted file mode 100644 index 63c0ce645e..0000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/SaveIgnoredUsersTask.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020 The Matrix.org Foundation C.I.C. - * - * 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 org.matrix.android.sdk.internal.session.user.accountdata - -import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.internal.database.model.IgnoredUserEntity -import org.matrix.android.sdk.internal.di.SessionDatabase -import org.matrix.android.sdk.internal.task.Task -import org.matrix.android.sdk.internal.util.awaitTransaction -import javax.inject.Inject - -/** - * Save the ignored users list in DB - */ -internal interface SaveIgnoredUsersTask : Task { - data class Params( - val userIds: List - ) -} - -internal class DefaultSaveIgnoredUsersTask @Inject constructor(@SessionDatabase private val monarchy: Monarchy) : SaveIgnoredUsersTask { - - override suspend fun execute(params: SaveIgnoredUsersTask.Params) { - monarchy.awaitTransaction { realm -> - // clear current ignored users - realm.where(IgnoredUserEntity::class.java) - .findAll() - .deleteAllFromRealm() - - // And save the new received list - params.userIds.forEach { realm.createObject(IgnoredUserEntity::class.java).apply { userId = it } } - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt index 445b78104c..173161f8ae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UpdateIgnoredUserIdsTask.kt @@ -38,7 +38,6 @@ internal interface UpdateIgnoredUserIdsTask : Task Date: Fri, 15 Apr 2022 13:06:53 +0200 Subject: [PATCH 07/10] ktlint --- .../settings/ignored/VectorSettingsIgnoredUsersFragment.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index 2ae7ba0a8d..3cb1e29016 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -30,8 +30,6 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding -import im.vector.app.features.MainActivity -import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import javax.inject.Inject From 749976a9cd427e79caf00e2e26ec121d4db8f92c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 13:31:49 +0200 Subject: [PATCH 08/10] changelog --- changelog.d/5772.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5772.feature diff --git a/changelog.d/5772.feature b/changelog.d/5772.feature new file mode 100644 index 0000000000..85eec0a1ad --- /dev/null +++ b/changelog.d/5772.feature @@ -0,0 +1 @@ +Improve management of ignored users \ No newline at end of file From cc8f086cc3974f6d1fc690ece7ee7f1cce02d14a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 13:32:30 +0200 Subject: [PATCH 09/10] copyright --- .../matrix/android/sdk/api/failure/InitialSyncRequestReason.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt index 5717f41f43..ebe07823f4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/InitialSyncRequestReason.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 903e226e5934a852f910ea5861de357bb33b4e2b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Apr 2022 16:30:09 +0200 Subject: [PATCH 10/10] Restart the timeline when some Event are deleted, for instance when ignoring a user, for the change to take effect --- .../session/room/timeline/DefaultTimeline.kt | 7 +++++++ .../session/room/timeline/LoadTimelineStrategy.kt | 4 +++- .../session/room/timeline/TimelineChunk.kt | 14 +++++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 5064ebf49b..08b2700a43 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -100,6 +100,7 @@ internal class DefaultTimeline(private val roomId: String, threadsAwarenessHandler = threadsAwarenessHandler, lightweightSettingsStorage = lightweightSettingsStorage, onEventsUpdated = this::sendSignalToPostSnapshot, + onEventsDeleted = this::onEventsDeleted, onLimitedTimeline = this::onLimitedTimeline, onNewTimelineEvents = this::onNewTimelineEvents ) @@ -304,6 +305,12 @@ internal class DefaultTimeline(private val roomId: String, } } + private fun onEventsDeleted() { + // Some event have been deleted, for instance when a user has been ignored. + // Restart the timeline (live) + restartWithEventId(null) + } + private suspend fun postSnapshot() { val snapshot = strategy.buildSnapshot() Timber.v("Post snapshot of ${snapshot.size} events") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt index ff986d04af..8819ffe69f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt @@ -95,6 +95,7 @@ internal class LoadTimelineStrategy( val threadsAwarenessHandler: ThreadsAwarenessHandler, val lightweightSettingsStorage: LightweightSettingsStorage, val onEventsUpdated: (Boolean) -> Unit, + val onEventsDeleted: () -> Unit, val onLimitedTimeline: () -> Unit, val onNewTimelineEvents: (List) -> Unit ) @@ -302,7 +303,8 @@ internal class LoadTimelineStrategy( threadsAwarenessHandler = dependencies.threadsAwarenessHandler, lightweightSettingsStorage = dependencies.lightweightSettingsStorage, initialEventId = mode.originEventId(), - onBuiltEvents = dependencies.onEventsUpdated + onBuiltEvents = dependencies.onEventsUpdated, + onEventsDeleted = dependencies.onEventsDeleted, ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt index 4ead1d4ecb..ca7bf8a0ac 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt @@ -59,11 +59,13 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity, private val realmConfiguration: RealmConfiguration, private val fetchTokenAndPaginateTask: FetchTokenAndPaginateTask, private val timelineEventMapper: TimelineEventMapper, - private val uiEchoManager: UIEchoManager? = null, + private val uiEchoManager: UIEchoManager?, private val threadsAwarenessHandler: ThreadsAwarenessHandler, private val lightweightSettingsStorage: LightweightSettingsStorage, private val initialEventId: String?, - private val onBuiltEvents: (Boolean) -> Unit) { + private val onBuiltEvents: (Boolean) -> Unit, + private val onEventsDeleted: () -> Unit, +) { private val isLastForward = AtomicBoolean(chunkEntity.isLastForward) private val isLastBackward = AtomicBoolean(chunkEntity.isLastBackward) @@ -505,6 +507,11 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity, if (insertions.isNotEmpty() || modifications.isNotEmpty()) { onBuiltEvents(true) } + + val deletions = changeSet.deletions + if (deletions.isNotEmpty()) { + onEventsDeleted() + } } private fun getNextDisplayIndex(direction: Timeline.Direction): Int? { @@ -543,7 +550,8 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity, threadsAwarenessHandler = threadsAwarenessHandler, lightweightSettingsStorage = lightweightSettingsStorage, initialEventId = null, - onBuiltEvents = this.onBuiltEvents + onBuiltEvents = this.onBuiltEvents, + onEventsDeleted = this.onEventsDeleted ) }