diff --git a/changelog.d/5761.feature b/changelog.d/5761.feature new file mode 100644 index 0000000000..3d30864e24 --- /dev/null +++ b/changelog.d/5761.feature @@ -0,0 +1 @@ +Improve user experience when home servers do not yet support threads \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 9db3876b74..597c1a0ca8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -54,7 +54,7 @@ data class HomeServerCapabilities( /** * True if the home server support threading */ - var canUseThreading: Boolean = false + val canUseThreading: Boolean = false ) { enum class RoomCapabilitySupport { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 9a73afd897..99c36d1190 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -452,6 +452,10 @@ class MessageActionsViewModel @AssistedInject constructor( actionPermissions: ActionPermissions): Boolean { // We let reply in thread visible even if threads are not enabled, with an enhanced flow to attract users // if (!vectorPreferences.areThreadMessagesEnabled()) return false + // Disable beta prompt if the homeserver do not support threads + if (!vectorPreferences.areThreadMessagesEnabled() && + !session.getHomeServerCapabilities().canUseThreading) return false + if (initialState.isFromThreadTimeline) return false if (event.root.isThread()) return false if (event.root.getClearType() != EventType.MESSAGE && diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt index 29f7df2439..545077b550 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt @@ -18,6 +18,7 @@ package im.vector.app.features.home.room.threads import android.app.Activity import android.text.Spanned +import androidx.annotation.StringRes import androidx.core.text.HtmlCompat import im.vector.app.R import im.vector.app.core.resources.StringProvider @@ -49,11 +50,17 @@ class ThreadsManager @Inject constructor( /** * Generates and return an Html spanned string to be rendered especially in dialogs */ - fun getBetaEnableThreadsMessage(): Spanned { + private fun generateLearnMoreHtmlString(@StringRes messageId: Int): Spanned { val learnMore = stringProvider.getString(R.string.action_learn_more) val learnMoreUrl = stringProvider.getString(R.string.threads_learn_more_url) val href = "$learnMore.

" - val message = stringProvider.getString(R.string.threads_beta_enable_notice_message, href) + val message = stringProvider.getString(messageId, href) return HtmlCompat.fromHtml(message, HtmlCompat.FROM_HTML_MODE_LEGACY) } + + fun getBetaEnableThreadsMessage(): Spanned = + generateLearnMoreHtmlString(R.string.threads_beta_enable_notice_message) + + fun getLabsEnableThreadsMessage(): Spanned = + generateLearnMoreHtmlString(R.string.threads_labs_enable_notice_message) } 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 0ef8e51429..c46a64ad31 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 @@ -17,18 +17,23 @@ package im.vector.app.features.settings import android.os.Bundle +import android.text.method.LinkMovementMethod +import android.widget.TextView import androidx.preference.Preference +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.preference.VectorSwitchPreference 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.home.room.threads.ThreadsManager import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import javax.inject.Inject class VectorSettingsLabsFragment @Inject constructor( private val vectorPreferences: VectorPreferences, - private val lightweightSettingsStorage: LightweightSettingsStorage + private val lightweightSettingsStorage: LightweightSettingsStorage, + private val threadsManager: ThreadsManager ) : VectorSettingsBaseFragment() { override var titleRes = R.string.room_settings_labs_pref_title @@ -46,15 +51,51 @@ class VectorSettingsLabsFragment @Inject constructor( } // clear cache - findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { - it.onPreferenceClickListener = Preference.OnPreferenceClickListener { - // We should migrate threads only if threads are disabled - vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled()) - lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) - displayLoadingView() - MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { vectorPref -> + vectorPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { + onThreadsPreferenceClickedInterceptor(vectorPref) false } } } + + /** + * Intercept the click to display a user friendly dialog when their homeserver do not support threads + */ + private fun onThreadsPreferenceClickedInterceptor(vectorSwitchPreference: VectorSwitchPreference) { + val userEnabledThreads = vectorPreferences.areThreadMessagesEnabled() + if (!session.getHomeServerCapabilities().canUseThreading && userEnabledThreads) { + activity?.let { + MaterialAlertDialogBuilder(it) + .setTitle(R.string.threads_labs_enable_notice_title) + .setMessage(threadsManager.getLabsEnableThreadsMessage()) + .setCancelable(true) + .setNegativeButton(R.string.action_not_now) { _, _ -> + vectorSwitchPreference.isChecked = false + } + .setPositiveButton(R.string.action_try_it_out) { _, _ -> + onThreadsPreferenceClicked() + } + .show() + ?.findViewById(android.R.id.message) + ?.apply { + linksClickable = true + movementMethod = LinkMovementMethod.getInstance() + } + } + } else { + onThreadsPreferenceClicked() + } + } + + /** + * Action when threads preference switch is actually clicked + */ + private fun onThreadsPreferenceClicked() { + // We should migrate threads only if threads are disabled + vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled()) + lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) + displayLoadingView() + MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 96ccef92f1..d849c1a58a 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -739,6 +739,9 @@ Threads Beta Threads help keep your conversations on-topic and easy to track. %sEnabling threads will refresh the app. This may take longer for some accounts. + Threads Beta + Your homeserver does not currently support threads, so this feature may be unreliable. Some threaded messages may not be reliably available. %sDo you want to enable threads anyway? + Search