From 2ca3387ab3648034f6e3a04f497e89eb415499bb Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Thu, 17 Mar 2022 18:51:54 +0100 Subject: [PATCH 01/10] Migrate Threads and notify user --- .../android/sdk/api/MatrixConfiguration.kt | 6 +- .../lightweight/LightweightSettingsStorage.kt | 8 ++- .../session/sync/SyncResponseHandler.kt | 2 +- .../src/main/res/values/config-settings.xml | 3 +- .../im/vector/app/core/di/SingletonModule.kt | 8 ++- .../im/vector/app/features/MainActivity.kt | 2 +- .../vector/app/features/home/HomeActivity.kt | 48 +++++++++++++++ .../features/home/HomeActivityViewEvents.kt | 3 + .../features/home/HomeActivityViewModel.kt | 46 +++++++++++++++ .../features/settings/VectorPreferences.kt | 58 ++++++++++++++++++- .../settings/VectorSettingsLabsFragment.kt | 1 + .../src/main/res/xml/vector_settings_labs.xml | 4 +- 12 files changed, 177 insertions(+), 12 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt index c87f21d7ac..f8472319fd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt @@ -60,7 +60,11 @@ data class MatrixConfiguration( /** * RoomDisplayNameFallbackProvider to provide default room display name. */ - val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider + val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider, + /** + * Thread messages default enable/disabled value + */ + val threadMessagesEnabledDefault: Boolean = false, ) { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt index 700b94a985..65c98ab872 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.database.lightweight import android.content.Context import androidx.core.content.edit import androidx.preference.PreferenceManager +import org.matrix.android.sdk.api.MatrixConfiguration import javax.inject.Inject /** @@ -27,7 +28,10 @@ import javax.inject.Inject * not for large data sets */ -class LightweightSettingsStorage @Inject constructor(context: Context) { +class LightweightSettingsStorage @Inject constructor( + context: Context, + val matrixConfiguration: MatrixConfiguration +) { private val sdkDefaultPrefs = PreferenceManager.getDefaultSharedPreferences(context.applicationContext) @@ -38,7 +42,7 @@ class LightweightSettingsStorage @Inject constructor(context: Context) { } fun areThreadMessagesEnabled(): Boolean { - return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, false) + return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, matrixConfiguration.threadMessagesEnabledDefault) } companion object { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt index 1bbf54a788..ac3ae3df91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt @@ -75,7 +75,7 @@ internal class SyncResponseHandler @Inject constructor( suspend fun handleResponse(syncResponse: SyncResponse, fromToken: String?, reporter: ProgressReporter?) { - val isInitialSync = fromToken == null + var isInitialSync = fromToken == null Timber.v("Start handling sync, is InitialSync: $isInitialSync") measureTimeMillis { diff --git a/vector-config/src/main/res/values/config-settings.xml b/vector-config/src/main/res/values/config-settings.xml index 0121ee9ae7..40fc68bbae 100755 --- a/vector-config/src/main/res/values/config-settings.xml +++ b/vector-config/src/main/res/values/config-settings.xml @@ -36,8 +36,9 @@ + false - + diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index a5575ef536..211bc3987f 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -46,6 +46,7 @@ import im.vector.app.features.navigation.Navigator import im.vector.app.features.pin.PinCodeStore import im.vector.app.features.pin.SharedPrefPinCodeStore import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider +import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.ui.SharedPreferencesUiStateRepository import im.vector.app.features.ui.UiStateRepository import kotlinx.coroutines.CoroutineScope @@ -113,10 +114,13 @@ object VectorStaticModule { } @Provides - fun providesMatrixConfiguration(vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration { + fun providesMatrixConfiguration( + vectorPreferences: VectorPreferences, + vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration { return MatrixConfiguration( applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, - roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider + roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider, + threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled() ) } diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt index 33b735551c..42bd2318b3 100644 --- a/vector/src/main/java/im/vector/app/features/MainActivity.kt +++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt @@ -241,7 +241,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity // We have a session. // Check it can be opened if (sessionHolder.getActiveSession().isOpenable) { - HomeActivity.newIntent(this) + HomeActivity.newIntent(this, existingSession = true) } else { // The token is still invalid navigator.softLogout(this) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 964fb6f365..1bd61c0f9e 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -90,6 +90,7 @@ import javax.inject.Inject data class HomeActivityArgs( val clearNotification: Boolean, val accountCreation: Boolean, + val existingSession: Boolean = false, val inviteNotificationRoomId: String? = null ) : Parcelable @@ -253,6 +254,8 @@ class HomeActivity : HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush() is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it) HomeActivityViewEvents.ShowAnalyticsOptIn -> handleShowAnalyticsOptIn() + HomeActivityViewEvents.NotifyUserForThreadsMigration -> handleNotifyUserForThreadsMigration() + is HomeActivityViewEvents.MigrateThreads -> migrateThreadsIfNeeded(it.checkSession) }.exhaustive } homeActivityViewModel.onEach { renderState(it) } @@ -269,6 +272,49 @@ class HomeActivity : navigator.openAnalyticsOptIn(this) } + /** + * Migrating from old threads io.element.thread to new m.thread needs an initial sync to + * sync and display existing messages appropriately + */ + private fun migrateThreadsIfNeeded(checkSession: Boolean) { + + if (checkSession) { + // We should check session to ensure we will only clear cache if needed + val args = intent.getParcelableExtra(Mavericks.KEY_ARG) + if (args?.existingSession == true) { + // existingSession --> Will be true only if we came from an existing active session + Timber.i("----> Migrating threads from an existing session..") + handleThreadsMigration() + } else { + // We came from a new session and not an existing one, + // so there is no need to migrate threads while an initial synced performed + Timber.i("----> No thread migration needed, we are ok") + vectorPreferences.threadsMigrated() + } + } else { + // Proceed with migration + handleThreadsMigration() + } + } + + /** + * Clear cache and restart to invoke an initial sync for threads migration + */ + private fun handleThreadsMigration() { + Timber.i("----> Threads Migration detected, clearing cache and sync...") + vectorPreferences.threadsMigrated() + MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) + } + + private fun handleNotifyUserForThreadsMigration() { + MaterialAlertDialogBuilder(this) + .setTitle("Threads, no longer experimental") + .setMessage("All \uD83C\uDF89 \uD83C\uDF89 threads created during experimental period will\n\n now be rendered as regular replies. This will be an one-off transition, as threads are now part of the matrix specification") + .setCancelable(true) + .setPositiveButton(R.string.ok) { _, _ -> } + .show() + } + private fun handleIntent(intent: Intent?) { intent?.dataString?.let { deepLink -> val resolvedLink = when { @@ -546,11 +592,13 @@ class HomeActivity : fun newIntent(context: Context, clearNotification: Boolean = false, accountCreation: Boolean = false, + existingSession: Boolean = false, inviteNotificationRoomId: String? = null ): Intent { val args = HomeActivityArgs( clearNotification = clearNotification, accountCreation = accountCreation, + existingSession = existingSession, inviteNotificationRoomId = inviteNotificationRoomId ) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt index adc44a57bd..e301967884 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt @@ -25,4 +25,7 @@ sealed interface HomeActivityViewEvents : VectorViewEvents { data class OnCrossSignedInvalidated(val userItem: MatrixItem.UserItem) : HomeActivityViewEvents object PromptToEnableSessionPush : HomeActivityViewEvents object ShowAnalyticsOptIn : HomeActivityViewEvents + object NotifyUserForThreadsMigration : HomeActivityViewEvents + data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents + } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index 35c112b63a..bb248965e4 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -51,6 +51,7 @@ 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.MXUsersDevicesMap +import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage import org.matrix.android.sdk.internal.util.awaitCallback import timber.log.Timber import kotlin.coroutines.Continuation @@ -62,6 +63,7 @@ class HomeActivityViewModel @AssistedInject constructor( private val activeSessionHolder: ActiveSessionHolder, private val reAuthHelper: ReAuthHelper, private val analyticsStore: AnalyticsStore, + private val lightweightSettingsStorage: LightweightSettingsStorage, private val vectorPreferences: VectorPreferences ) : VectorViewModel(initialState) { @@ -84,6 +86,7 @@ class HomeActivityViewModel @AssistedInject constructor( checkSessionPushIsOn() observeCrossSigningReset() observeAnalytics() + initThreadsMigration() } private fun observeAnalytics() { @@ -130,6 +133,49 @@ class HomeActivityViewModel @AssistedInject constructor( .launchIn(viewModelScope) } + /** + * Handle threads migration. The migration includes: + * - Notify users that had io.element.thread enabled from labs + * - Re-Enable m.thread to those users (that they had enabled labs threads) + * - Handle migration when threads are enabled by default + */ + private fun initThreadsMigration() { + + // Notify users + if (vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled()) { + Timber.i("----> Notify users about threads") + // Notify the user if needed that we migrated to support m.thread + // instead of io.element.thread so old thread messages will be displayed as normal timeline messages + _viewEvents.post(HomeActivityViewEvents.NotifyUserForThreadsMigration) + vectorPreferences.userNotifiedAboutThreads() + return + } + + // Migrate users with enabled lab settings + if (vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.shouldMigrateThreads()) { + Timber.i("----> Migrate threads with enabled labs") + // If user had io.element.thread enabled then enable the new thread support, + // clear cache to sync messages appropriately + vectorPreferences.setThreadMessagesEnabled() + lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) + // Clear Cache + _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = false)) + return + } + // Enable all users + // When we would to enable threads for all + // if(vectorPreferences.shouldMigrateThreads) --> + // vectorPreferences.setThreadMessagesEnabled() && + // lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) + if(vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled()){ + Timber.i("----> Try to migrate threads") + _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true)) + return + } + + + } + private fun observeInitialSync() { val session = activeSessionHolder.getSafeActiveSession() ?: return diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 352c5768fb..d263dc1cbb 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -201,7 +201,13 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val TAKE_PHOTO_VIDEO_MODE = "TAKE_PHOTO_VIDEO_MODE" private const val SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE = "SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE" - const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES" + + // This key will be used to identify clients with the old thread support enabled io.element.thread + const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES" + + // This key will be used to identify clients with the new thread support enabled m.thread + const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES_FINAL" + const val SETTINGS_THREAD_MESSAGES_SYNCED = "SETTINGS_THREAD_MESSAGES_SYNCED" // Possible values for TAKE_PHOTO_VIDEO_MODE const val TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK = 0 @@ -1006,7 +1012,55 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_LABS_RENDER_LOCATIONS_IN_TIMELINE, true) } + /** + * Indicates whether or not thread messages are enabled + */ fun areThreadMessagesEnabled(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, false) + return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, getDefault(R.bool.settings_labs_thread_messages_default)) + } + + /** + * Manually sets thread messages enabled, useful for migrating users from io.element.thread + */ + fun setThreadMessagesEnabled() { + defaultPrefs + .edit() + .putBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, true) + .apply() + } + /** + * Indicates whether or not the user will be notified about the new thread support + * We should notify the user only if he had old thread support enabled + */ + fun shouldNotifyUserAboutThreads(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS, false) + } + + /** + * Indicates that the user have been notified about threads migration + */ + fun userNotifiedAboutThreads() { + defaultPrefs + .edit() + .putBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES_OLD_CLIENTS, false) + .apply() + } + + /** + * Indicates whether or not we should clear cache for threads migration. + * Default value is true, for fresh installs and updates + */ + fun shouldMigrateThreads(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, true) + } + + /** + * Indicates that there no longer threads migration needed + */ + fun threadsMigrated() { + defaultPrefs + .edit() + .putBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, false) + .apply() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt index 118e820f84..683c1e1dd2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt @@ -42,6 +42,7 @@ class VectorSettingsLabsFragment @Inject constructor( // clear cache findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { it.onPreferenceClickListener = Preference.OnPreferenceClickListener { + vectorPreferences.threadsMigrated() // Manual actions should disable the ato enable mechanism lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) displayLoadingView() MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) diff --git a/vector/src/main/res/xml/vector_settings_labs.xml b/vector/src/main/res/xml/vector_settings_labs.xml index 73193edfd5..5144f6fe1f 100644 --- a/vector/src/main/res/xml/vector_settings_labs.xml +++ b/vector/src/main/res/xml/vector_settings_labs.xml @@ -52,8 +52,8 @@ From 61cb7a6ffb41a8775eb9389923c346b7736b5456 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Thu, 17 Mar 2022 19:09:09 +0100 Subject: [PATCH 02/10] Prepare next RC threads migration to all users --- .../im/vector/app/features/home/HomeActivityViewModel.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index bb248965e4..ba91ac7ae1 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -164,9 +164,10 @@ class HomeActivityViewModel @AssistedInject constructor( } // Enable all users // When we would to enable threads for all - // if(vectorPreferences.shouldMigrateThreads) --> - // vectorPreferences.setThreadMessagesEnabled() && - // lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) +// if(vectorPreferences.shouldMigrateThreads()) { +// vectorPreferences.setThreadMessagesEnabled() +// lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) +// } if(vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled()){ Timber.i("----> Try to migrate threads") _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true)) From f00b1f29bf5562c7f767f0758a16b9e92c5d0fe8 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 18 Mar 2022 11:58:29 +0100 Subject: [PATCH 03/10] Enhance text context for thread migration notice --- .../main/java/im/vector/app/features/home/HomeActivity.kt | 7 +++---- .../im/vector/app/features/home/HomeActivityViewEvents.kt | 1 - .../im/vector/app/features/home/HomeActivityViewModel.kt | 5 +---- vector/src/main/res/values/strings.xml | 2 ++ 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 1bd61c0f9e..f6ee160104 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -277,7 +277,6 @@ class HomeActivity : * sync and display existing messages appropriately */ private fun migrateThreadsIfNeeded(checkSession: Boolean) { - if (checkSession) { // We should check session to ensure we will only clear cache if needed val args = intent.getParcelableExtra(Mavericks.KEY_ARG) @@ -308,10 +307,10 @@ class HomeActivity : private fun handleNotifyUserForThreadsMigration() { MaterialAlertDialogBuilder(this) - .setTitle("Threads, no longer experimental") - .setMessage("All \uD83C\uDF89 \uD83C\uDF89 threads created during experimental period will\n\n now be rendered as regular replies. This will be an one-off transition, as threads are now part of the matrix specification") + .setTitle(R.string.threads_notice_migration_title) + .setMessage(R.string.threads_notice_migration_message) .setCancelable(true) - .setPositiveButton(R.string.ok) { _, _ -> } + .setPositiveButton(R.string.sas_got_it) { _, _ -> } .show() } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt index e301967884..5efd49a579 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewEvents.kt @@ -27,5 +27,4 @@ sealed interface HomeActivityViewEvents : VectorViewEvents { object ShowAnalyticsOptIn : HomeActivityViewEvents object NotifyUserForThreadsMigration : HomeActivityViewEvents data class MigrateThreads(val checkSession: Boolean) : HomeActivityViewEvents - } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index ba91ac7ae1..e6a7fd37a2 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -140,7 +140,6 @@ class HomeActivityViewModel @AssistedInject constructor( * - Handle migration when threads are enabled by default */ private fun initThreadsMigration() { - // Notify users if (vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled()) { Timber.i("----> Notify users about threads") @@ -168,13 +167,11 @@ class HomeActivityViewModel @AssistedInject constructor( // vectorPreferences.setThreadMessagesEnabled() // lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) // } - if(vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled()){ + if (vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled()) { Timber.i("----> Try to migrate threads") _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true)) return } - - } private fun observeInitialSync() { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 162ab3e119..fbb3b81efa 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -731,6 +731,8 @@ Tip: Long tap a message and use β€œ%s”. From a Thread + Threads no longer experimental + All threads created during the experimental period will now be rendered as regular replies.\n\nThis will be a one-off transition, as threads are now part of the Matrix specification.\n\nThank you for helping us test Threads! πŸŽ‰ Search From 2e5d45ec6e9e403cf047c2aa2954babff4da36f2 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 18 Mar 2022 12:03:17 +0100 Subject: [PATCH 04/10] Format code --- .../java/im/vector/app/features/settings/VectorPreferences.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index d263dc1cbb..bd20c57ca5 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1028,6 +1028,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { .putBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, true) .apply() } + /** * Indicates whether or not the user will be notified about the new thread support * We should notify the user only if he had old thread support enabled From fd4d99d6fce5ecd9705410107de83ecd4df34977 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 18 Mar 2022 14:50:34 +0100 Subject: [PATCH 05/10] Possible NullPointerException crash fix --- .../matrix/android/sdk/internal/di/WorkManagerProvider.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt index 7d004bc5c0..e6143b4dc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt @@ -31,6 +31,7 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory +import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -80,8 +81,8 @@ internal class WorkManagerProvider @Inject constructor( workManager.enqueue(checkWorkerRequest) val checkWorkerLiveState = workManager.getWorkInfoByIdLiveData(checkWorkerRequest.id) val observer = object : Observer { - override fun onChanged(workInfo: WorkInfo) { - if (workInfo.state.isFinished) { + override fun onChanged(workInfo: WorkInfo?) { + if (workInfo?.state?.isFinished == true) { checkWorkerLiveState.removeObserver(this) if (workInfo.state == WorkInfo.State.FAILED) { throw RuntimeException("MatrixWorkerFactory is not being set on your worker configuration.\n" + From 06db7e2374039ba0860ed9faef9ccacbed11111b Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 18 Mar 2022 14:51:06 +0100 Subject: [PATCH 06/10] Enhance migration logic & PR remarks --- .../session/sync/SyncResponseHandler.kt | 2 +- .../vector/app/features/home/HomeActivity.kt | 4 +- .../features/home/HomeActivityViewModel.kt | 53 +++++++++---------- .../features/settings/VectorPreferences.kt | 4 +- .../settings/VectorSettingsLabsFragment.kt | 3 +- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt index ac3ae3df91..1bbf54a788 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt @@ -75,7 +75,7 @@ internal class SyncResponseHandler @Inject constructor( suspend fun handleResponse(syncResponse: SyncResponse, fromToken: String?, reporter: ProgressReporter?) { - var isInitialSync = fromToken == null + val isInitialSync = fromToken == null Timber.v("Start handling sync, is InitialSync: $isInitialSync") measureTimeMillis { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index f6ee160104..dbeb5d5b8f 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -288,7 +288,7 @@ class HomeActivity : // We came from a new session and not an existing one, // so there is no need to migrate threads while an initial synced performed Timber.i("----> No thread migration needed, we are ok") - vectorPreferences.threadsMigrated() + vectorPreferences.setShouldMigrateThreads(shouldMigrate = false) } } else { // Proceed with migration @@ -301,7 +301,7 @@ class HomeActivity : */ private fun handleThreadsMigration() { Timber.i("----> Threads Migration detected, clearing cache and sync...") - vectorPreferences.threadsMigrated() + vectorPreferences.setShouldMigrateThreads(shouldMigrate = false) MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index e6a7fd37a2..b4af50c7ff 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -140,37 +140,36 @@ class HomeActivityViewModel @AssistedInject constructor( * - Handle migration when threads are enabled by default */ private fun initThreadsMigration() { - // Notify users - if (vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled()) { - Timber.i("----> Notify users about threads") - // Notify the user if needed that we migrated to support m.thread - // instead of io.element.thread so old thread messages will be displayed as normal timeline messages - _viewEvents.post(HomeActivityViewEvents.NotifyUserForThreadsMigration) - vectorPreferences.userNotifiedAboutThreads() - return - } - - // Migrate users with enabled lab settings - if (vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.shouldMigrateThreads()) { - Timber.i("----> Migrate threads with enabled labs") - // If user had io.element.thread enabled then enable the new thread support, - // clear cache to sync messages appropriately - vectorPreferences.setThreadMessagesEnabled() - lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) - // Clear Cache - _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = false)) - return - } - // Enable all users - // When we would to enable threads for all + // When we would like to enable threads for all users // if(vectorPreferences.shouldMigrateThreads()) { // vectorPreferences.setThreadMessagesEnabled() // lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) // } - if (vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled()) { - Timber.i("----> Try to migrate threads") - _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true)) - return + + when { + // Notify users + vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.areThreadMessagesEnabled() -> { + Timber.i("----> Notify users about threads") + // Notify the user if needed that we migrated to support m.thread + // instead of io.element.thread so old thread messages will be displayed as normal timeline messages + _viewEvents.post(HomeActivityViewEvents.NotifyUserForThreadsMigration) + vectorPreferences.userNotifiedAboutThreads() + } + // Migrate users with enabled lab settings + vectorPreferences.shouldNotifyUserAboutThreads() && vectorPreferences.shouldMigrateThreads() -> { + Timber.i("----> Migrate threads with enabled labs") + // If user had io.element.thread enabled then enable the new thread support, + // clear cache to sync messages appropriately + vectorPreferences.setThreadMessagesEnabled() + lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) + // Clear Cache + _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = false)) + } + // Enable all users + vectorPreferences.shouldMigrateThreads() && vectorPreferences.areThreadMessagesEnabled() -> { + Timber.i("----> Try to migrate threads") + _viewEvents.post(HomeActivityViewEvents.MigrateThreads(checkSession = true)) + } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index bd20c57ca5..8d93edc0ec 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -1058,10 +1058,10 @@ class VectorPreferences @Inject constructor(private val context: Context) { /** * Indicates that there no longer threads migration needed */ - fun threadsMigrated() { + fun setShouldMigrateThreads(shouldMigrate: Boolean) { defaultPrefs .edit() - .putBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, false) + .putBoolean(SETTINGS_THREAD_MESSAGES_SYNCED, shouldMigrate) .apply() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt index 683c1e1dd2..003832fb97 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt @@ -42,7 +42,8 @@ class VectorSettingsLabsFragment @Inject constructor( // clear cache findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { it.onPreferenceClickListener = Preference.OnPreferenceClickListener { - vectorPreferences.threadsMigrated() // Manual actions should disable the ato enable mechanism + // We should migrate threads only if threads are disabled + vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled()) lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) displayLoadingView() MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) From e574fda0993fca8d483507300cffbe28ff7acef8 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Fri, 18 Mar 2022 14:55:14 +0100 Subject: [PATCH 07/10] Remove unused import --- .../org/matrix/android/sdk/internal/di/WorkManagerProvider.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt index e6143b4dc8..fedd7d05f9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt @@ -31,7 +31,6 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory -import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject From ed2cb5f0fe20102afd2db43f1eb9dd243730f254 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Mon, 21 Mar 2022 15:45:08 +0200 Subject: [PATCH 08/10] Enhance text constants --- vector/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index fbb3b81efa..1ce3a4f87e 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -731,8 +731,8 @@ Tip: Long tap a message and use β€œ%s”. From a Thread - Threads no longer experimental - All threads created during the experimental period will now be rendered as regular replies.\n\nThis will be a one-off transition, as threads are now part of the Matrix specification.\n\nThank you for helping us test Threads! πŸŽ‰ + Threads Approaching Beta πŸŽ‰ + We’re getting closer to releasing a public Beta for Threads.\n\nAs we prepare for it, we need to make some changes: threads created before this point will be displayed as regular replies.\n\nThis will be a one-off transition as Threads are now part of the Matrix specification. Search From a431d885f0323897e875db42bf4f13b21a6ff736 Mon Sep 17 00:00:00 2001 From: ariskotsomitopoulos Date: Tue, 22 Mar 2022 11:20:47 +0200 Subject: [PATCH 09/10] Increase the thread summaries limit --- .../session/room/relation/threads/FetchThreadSummariesTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt index d316eed691..b596f2288e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadSummariesTask.kt @@ -44,7 +44,7 @@ internal interface FetchThreadSummariesTask : Task Date: Tue, 22 Mar 2022 13:57:20 +0200 Subject: [PATCH 10/10] PR remarks --- .../database/lightweight/LightweightSettingsStorage.kt | 4 ++-- .../main/java/im/vector/app/features/home/HomeActivity.kt | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt index 65c98ab872..069e539e2c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt @@ -24,13 +24,13 @@ import javax.inject.Inject /** * The purpose of this class is to provide an alternative and lightweight way to store settings/data - * on the sdi without using the database. This should be used just for sdk/user preferences and + * on the sdk without using the database. This should be used just for sdk/user preferences and * not for large data sets */ class LightweightSettingsStorage @Inject constructor( context: Context, - val matrixConfiguration: MatrixConfiguration + private val matrixConfiguration: MatrixConfiguration ) { private val sdkDefaultPrefs = PreferenceManager.getDefaultSharedPreferences(context.applicationContext) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index dbeb5d5b8f..2e9ab0efcb 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -90,7 +90,7 @@ import javax.inject.Inject data class HomeActivityArgs( val clearNotification: Boolean, val accountCreation: Boolean, - val existingSession: Boolean = false, + val hasExistingSession: Boolean = false, val inviteNotificationRoomId: String? = null ) : Parcelable @@ -280,7 +280,7 @@ class HomeActivity : if (checkSession) { // We should check session to ensure we will only clear cache if needed val args = intent.getParcelableExtra(Mavericks.KEY_ARG) - if (args?.existingSession == true) { + if (args?.hasExistingSession == true) { // existingSession --> Will be true only if we came from an existing active session Timber.i("----> Migrating threads from an existing session..") handleThreadsMigration() @@ -597,7 +597,7 @@ class HomeActivity : val args = HomeActivityArgs( clearNotification = clearNotification, accountCreation = accountCreation, - existingSession = existingSession, + hasExistingSession = existingSession, inviteNotificationRoomId = inviteNotificationRoomId )