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