mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
- Add threads to lab settings
- Disable thread awareness due to the new fallback mechanism
This commit is contained in:
parent
4cff3938e7
commit
8cc96e27bc
23 changed files with 116 additions and 58 deletions
|
@ -96,6 +96,11 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not thread messages are enabled
|
||||||
|
*/
|
||||||
|
var areThreadMessagesEnabled: Boolean = false
|
||||||
|
|
||||||
private lateinit var instance: Matrix
|
private lateinit var instance: Matrix
|
||||||
private val isInit = AtomicBoolean(false)
|
private val isInit = AtomicBoolean(false)
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ internal fun Map<String, EventEntity>.updateThreadSummaryIfNeeded(
|
||||||
roomId: String,
|
roomId: String,
|
||||||
realm: Realm, currentUserId: String,
|
realm: Realm, currentUserId: String,
|
||||||
shouldUpdateNotifications: Boolean = true) {
|
shouldUpdateNotifications: Boolean = true) {
|
||||||
if (!BuildConfig.THREADING_ENABLED) return
|
|
||||||
|
|
||||||
for ((rootThreadEventId, eventEntity) in this) {
|
for ((rootThreadEventId, eventEntity) in this) {
|
||||||
eventEntity.findAllThreadsForRootEventId(eventEntity.realm, rootThreadEventId).let {
|
eventEntity.findAllThreadsForRootEventId(eventEntity.realm, rootThreadEventId).let {
|
||||||
|
|
|
@ -295,7 +295,8 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
if (timelineEvents.isEmpty()) return LoadedFromStorage()
|
if (timelineEvents.isEmpty()) return LoadedFromStorage()
|
||||||
fetchRootThreadEventsIfNeeded(timelineEvents)
|
// Disabled due to the new fallback
|
||||||
|
// fetchRootThreadEventsIfNeeded(timelineEvents)
|
||||||
if (direction == Timeline.Direction.FORWARDS) {
|
if (direction == Timeline.Direction.FORWARDS) {
|
||||||
builtEventsIndexes.entries.forEach { it.setValue(it.value + timelineEvents.size) }
|
builtEventsIndexes.entries.forEach { it.setValue(it.value + timelineEvents.size) }
|
||||||
}
|
}
|
||||||
|
@ -332,7 +333,7 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
||||||
* in order to be able to display the event to the user appropriately
|
* in order to be able to display the event to the user appropriately
|
||||||
*/
|
*/
|
||||||
private suspend fun fetchRootThreadEventsIfNeeded(offsetResults: List<TimelineEventEntity>) {
|
private suspend fun fetchRootThreadEventsIfNeeded(offsetResults: List<TimelineEventEntity>) {
|
||||||
if (BuildConfig.THREADING_ENABLED) return
|
// if (BuildConfig.THREADING_ENABLED) return
|
||||||
val eventEntityList = offsetResults
|
val eventEntityList = offsetResults
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
it.root
|
it.root
|
||||||
|
|
|
@ -116,15 +116,16 @@ internal class TimelineEventDecryptor @Inject constructor(
|
||||||
|
|
||||||
eventEntity?.apply {
|
eventEntity?.apply {
|
||||||
val decryptedPayload =
|
val decryptedPayload =
|
||||||
if (!BuildConfig.THREADING_ENABLED) {
|
// Disabled due to the new fallback
|
||||||
threadsAwarenessHandler.handleIfNeededDuringDecryption(
|
// if (!BuildConfig.THREADING_ENABLED) {
|
||||||
it,
|
// threadsAwarenessHandler.handleIfNeededDuringDecryption(
|
||||||
roomId = event.roomId,
|
// it,
|
||||||
event,
|
// roomId = event.roomId,
|
||||||
result)
|
// event,
|
||||||
} else {
|
// result)
|
||||||
|
// } else {
|
||||||
null
|
null
|
||||||
}
|
// }
|
||||||
setDecryptionResult(result, decryptedPayload)
|
setDecryptionResult(result, decryptedPayload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.matrix.android.sdk.internal.session.room.timeline
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
import org.matrix.android.sdk.api.Matrix
|
||||||
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
|
@ -50,6 +52,7 @@ import javax.inject.Inject
|
||||||
internal class TokenChunkEventPersistor @Inject constructor(
|
internal class TokenChunkEventPersistor @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
@UserId private val userId: String,
|
@UserId private val userId: String,
|
||||||
|
private val matrixConfiguration: MatrixConfiguration,
|
||||||
private val liveEventManager: Lazy<StreamEventsManager>) {
|
private val liveEventManager: Lazy<StreamEventsManager>) {
|
||||||
|
|
||||||
enum class Result {
|
enum class Result {
|
||||||
|
@ -182,18 +185,22 @@ internal class TokenChunkEventPersistor @Inject constructor(
|
||||||
}
|
}
|
||||||
liveEventManager.get().dispatchPaginatedEventReceived(event, roomId)
|
liveEventManager.get().dispatchPaginatedEventReceived(event, roomId)
|
||||||
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser)
|
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser)
|
||||||
eventEntity.rootThreadEventId?.let {
|
if(Matrix.areThreadMessagesEnabled) {
|
||||||
// This is a thread event
|
eventEntity.rootThreadEventId?.let {
|
||||||
optimizedThreadSummaryMap[it] = eventEntity
|
// This is a thread event
|
||||||
} ?: run {
|
optimizedThreadSummaryMap[it] = eventEntity
|
||||||
// This is a normal event or a root thread one
|
} ?: run {
|
||||||
optimizedThreadSummaryMap[eventEntity.eventId] = eventEntity
|
// This is a normal event or a root thread one
|
||||||
|
optimizedThreadSummaryMap[eventEntity.eventId] = eventEntity
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentChunk.isValid) {
|
if (currentChunk.isValid) {
|
||||||
RoomEntity.where(realm, roomId).findFirst()?.addIfNecessary(currentChunk)
|
RoomEntity.where(realm, roomId).findFirst()?.addIfNecessary(currentChunk)
|
||||||
}
|
}
|
||||||
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(roomId = roomId, realm = realm, currentUserId = userId)
|
if(Matrix.areThreadMessagesEnabled) {
|
||||||
|
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(roomId = roomId, realm = realm, currentUserId = userId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,9 +102,10 @@ internal class SyncResponseHandler @Inject constructor(
|
||||||
val aggregator = SyncResponsePostTreatmentAggregator()
|
val aggregator = SyncResponsePostTreatmentAggregator()
|
||||||
|
|
||||||
// Prerequisite for thread events handling in RoomSyncHandler
|
// Prerequisite for thread events handling in RoomSyncHandler
|
||||||
if (!BuildConfig.THREADING_ENABLED) {
|
// Disabled due to the new fallback
|
||||||
threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(syncResponse)
|
// if (!BuildConfig.THREADING_ENABLED) {
|
||||||
}
|
// threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(syncResponse)
|
||||||
|
// }
|
||||||
|
|
||||||
// Start one big transaction
|
// Start one big transaction
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
|
|
|
@ -19,7 +19,8 @@ package org.matrix.android.sdk.internal.session.sync.handler.room
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
import org.matrix.android.sdk.BuildConfig
|
import org.matrix.android.sdk.api.Matrix
|
||||||
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
@ -82,6 +83,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
private val roomMemberEventHandler: RoomMemberEventHandler,
|
private val roomMemberEventHandler: RoomMemberEventHandler,
|
||||||
private val roomTypingUsersHandler: RoomTypingUsersHandler,
|
private val roomTypingUsersHandler: RoomTypingUsersHandler,
|
||||||
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
|
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
|
||||||
|
private val matrixConfiguration: MatrixConfiguration,
|
||||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||||
@UserId private val userId: String,
|
@UserId private val userId: String,
|
||||||
private val timelineInput: TimelineInput,
|
private val timelineInput: TimelineInput,
|
||||||
|
@ -379,13 +381,13 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
if (event.isEncrypted() && !isInitialSync) {
|
if (event.isEncrypted() && !isInitialSync) {
|
||||||
decryptIfNeeded(event, roomId)
|
decryptIfNeeded(event, roomId)
|
||||||
}
|
}
|
||||||
|
// Disabled due to the new fallback
|
||||||
if (!BuildConfig.THREADING_ENABLED) {
|
// if (!BuildConfig.THREADING_ENABLED) {
|
||||||
threadsAwarenessHandler.handleIfNeeded(
|
// threadsAwarenessHandler.handleIfNeeded(
|
||||||
realm = realm,
|
// realm = realm,
|
||||||
roomId = roomId,
|
// roomId = roomId,
|
||||||
event = event)
|
// event = event)
|
||||||
}
|
// }
|
||||||
|
|
||||||
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
|
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
|
||||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, insertType)
|
val eventEntity = event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, insertType)
|
||||||
|
@ -408,12 +410,14 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser)
|
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser)
|
||||||
eventEntity.rootThreadEventId?.let {
|
if(Matrix.areThreadMessagesEnabled) {
|
||||||
// This is a thread event
|
eventEntity.rootThreadEventId?.let {
|
||||||
optimizedThreadSummaryMap[it] = eventEntity
|
// This is a thread event
|
||||||
} ?: run {
|
optimizedThreadSummaryMap[it] = eventEntity
|
||||||
// This is a normal event or a root thread one
|
} ?: run {
|
||||||
optimizedThreadSummaryMap[eventEntity.eventId] = eventEntity
|
// This is a normal event or a root thread one
|
||||||
|
optimizedThreadSummaryMap[eventEntity.eventId] = eventEntity
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give info to crypto module
|
// Give info to crypto module
|
||||||
|
@ -442,10 +446,12 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||||
}
|
}
|
||||||
// Handle deletion of [stuck] local echos if needed
|
// Handle deletion of [stuck] local echos if needed
|
||||||
deleteLocalEchosIfNeeded(insertType, roomEntity, eventList)
|
deleteLocalEchosIfNeeded(insertType, roomEntity, eventList)
|
||||||
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(
|
if(Matrix.areThreadMessagesEnabled) {
|
||||||
roomId = roomId,
|
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(
|
||||||
realm = realm,
|
roomId = roomId,
|
||||||
currentUserId = userId)
|
realm = realm,
|
||||||
|
currentUserId = userId)
|
||||||
|
}
|
||||||
|
|
||||||
// posting new events to timeline if any is registered
|
// posting new events to timeline if any is registered
|
||||||
timelineInput.onNewTimelineEvents(roomId = roomId, eventIds = eventIds)
|
timelineInput.onNewTimelineEvents(roomId = roomId, eventIds = eventIds)
|
||||||
|
|
|
@ -83,6 +83,7 @@ import im.vector.app.features.themes.ThemeUtils
|
||||||
import im.vector.app.receivers.DebugReceiver
|
import im.vector.app.receivers.DebugReceiver
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import org.matrix.android.sdk.api.Matrix
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.failure.GlobalError
|
import org.matrix.android.sdk.api.failure.GlobalError
|
||||||
import reactivecircus.flowbinding.android.view.clicks
|
import reactivecircus.flowbinding.android.view.clicks
|
||||||
|
@ -193,6 +194,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
||||||
navigator = singletonEntryPoint.navigator()
|
navigator = singletonEntryPoint.navigator()
|
||||||
activeSessionHolder = singletonEntryPoint.activeSessionHolder()
|
activeSessionHolder = singletonEntryPoint.activeSessionHolder()
|
||||||
vectorPreferences = singletonEntryPoint.vectorPreferences()
|
vectorPreferences = singletonEntryPoint.vectorPreferences()
|
||||||
|
Matrix.areThreadMessagesEnabled = vectorPreferences.areThreadMessagesEnabled()
|
||||||
configurationViewModel.activityRestarter.observe(this) {
|
configurationViewModel.activityRestarter.observe(this) {
|
||||||
if (!it.hasBeenHandled) {
|
if (!it.hasBeenHandled) {
|
||||||
// Recreate the Activity because configuration has changed
|
// Recreate the Activity because configuration has changed
|
||||||
|
|
|
@ -52,4 +52,8 @@ class UserPreferencesProvider @Inject constructor(private val vectorPreferences:
|
||||||
fun shouldShowPolls(): Boolean {
|
fun shouldShowPolls(): Boolean {
|
||||||
return vectorPreferences.labsEnablePolls()
|
return vectorPreferences.labsEnablePolls()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun areThreadMessagesEnabled(): Boolean {
|
||||||
|
return vectorPreferences.areThreadMessagesEnabled()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class AutocompleteCommandPresenter @AssistedInject constructor(
|
||||||
!it.isDevCommand || vectorPreferences.developerMode()
|
!it.isDevCommand || vectorPreferences.developerMode()
|
||||||
}
|
}
|
||||||
.filter {
|
.filter {
|
||||||
if (BuildConfig.THREADING_ENABLED && isInThreadTimeline) {
|
if (vectorPreferences.areThreadMessagesEnabled() && isInThreadTimeline) {
|
||||||
it.isThreadCommand
|
it.isThreadCommand
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
|
|
@ -65,7 +65,7 @@ object CommandParser {
|
||||||
val slashCommand = messageParts.first()
|
val slashCommand = messageParts.first()
|
||||||
val message = textMessage.substring(slashCommand.length).trim()
|
val message = textMessage.substring(slashCommand.length).trim()
|
||||||
|
|
||||||
if (BuildConfig.THREADING_ENABLED && isInThreadTimeline) {
|
if (isInThreadTimeline) {
|
||||||
val notSupportedCommandsInThreads = Command.values().filter {
|
val notSupportedCommandsInThreads = Command.values().filter {
|
||||||
!it.isThreadCommand
|
!it.isThreadCommand
|
||||||
}.map {
|
}.map {
|
||||||
|
|
|
@ -1958,7 +1958,7 @@ class TimelineFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onThreadSummaryClicked(eventId: String, isRootThreadEvent: Boolean) {
|
override fun onThreadSummaryClicked(eventId: String, isRootThreadEvent: Boolean) {
|
||||||
if (BuildConfig.THREADING_ENABLED && isRootThreadEvent && !isThreadTimeLine()) {
|
if (vectorPreferences.areThreadMessagesEnabled() && isRootThreadEvent && !isThreadTimeLine()) {
|
||||||
navigateToThreadTimeline(eventId)
|
navigateToThreadTimeline(eventId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -695,7 +695,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
// Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^
|
// Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^
|
||||||
R.id.join_conference -> !state.isWebRTCCallOptionAvailable() && state.jitsiState.confId != null && !state.jitsiState.hasJoined
|
R.id.join_conference -> !state.isWebRTCCallOptionAvailable() && state.jitsiState.confId != null && !state.jitsiState.hasJoined
|
||||||
R.id.search -> true
|
R.id.search -> true
|
||||||
R.id.menu_timeline_thread_list -> BuildConfig.THREADING_ENABLED
|
R.id.menu_timeline_thread_list -> vectorPreferences.areThreadMessagesEnabled()
|
||||||
R.id.dev_tools -> vectorPreferences.developerMode()
|
R.id.dev_tools -> vectorPreferences.developerMode()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.app.core.epoxy.charsequence.toEpoxyCharSequence
|
||||||
import im.vector.app.core.epoxy.loadingItem
|
import im.vector.app.core.epoxy.loadingItem
|
||||||
import im.vector.app.core.epoxy.noResultItem
|
import im.vector.app.core.epoxy.noResultItem
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.core.resources.UserPreferencesProvider
|
||||||
import im.vector.app.core.ui.list.GenericHeaderItem_
|
import im.vector.app.core.ui.list.GenericHeaderItem_
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -43,7 +44,8 @@ class SearchResultController @Inject constructor(
|
||||||
private val session: Session,
|
private val session: Session,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val dateFormatter: VectorDateFormatter
|
private val dateFormatter: VectorDateFormatter,
|
||||||
|
private val userPreferencesProvider: UserPreferencesProvider
|
||||||
) : TypedEpoxyController<SearchViewState>() {
|
) : TypedEpoxyController<SearchViewState>() {
|
||||||
|
|
||||||
var listener: Listener? = null
|
var listener: Listener? = null
|
||||||
|
@ -123,6 +125,7 @@ class SearchResultController @Inject constructor(
|
||||||
.sender(eventAndSender.sender
|
.sender(eventAndSender.sender
|
||||||
?: eventAndSender.event.senderId?.let { session.getRoomMember(it, data.roomId) }?.toMatrixItem())
|
?: eventAndSender.event.senderId?.let { session.getRoomMember(it, data.roomId) }?.toMatrixItem())
|
||||||
.threadDetails(event.threadDetails)
|
.threadDetails(event.threadDetails)
|
||||||
|
.areThreadMessagesEnabled(userPreferencesProvider.areThreadMessagesEnabled())
|
||||||
.listener { listener?.onItemClicked(eventAndSender.event) }
|
.listener { listener?.onItemClicked(eventAndSender.event) }
|
||||||
.let { result.add(it) }
|
.let { result.add(it) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
|
||||||
@EpoxyAttribute lateinit var spannable: EpoxyCharSequence
|
@EpoxyAttribute lateinit var spannable: EpoxyCharSequence
|
||||||
@EpoxyAttribute var sender: MatrixItem? = null
|
@EpoxyAttribute var sender: MatrixItem? = null
|
||||||
@EpoxyAttribute var threadDetails: ThreadDetails? = null
|
@EpoxyAttribute var threadDetails: ThreadDetails? = null
|
||||||
|
@EpoxyAttribute var areThreadMessagesEnabled: Boolean = false
|
||||||
|
|
||||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
|
||||||
holder.timeView.text = formattedDate
|
holder.timeView.text = formattedDate
|
||||||
holder.contentView.text = spannable.charSequence
|
holder.contentView.text = spannable.charSequence
|
||||||
|
|
||||||
if (BuildConfig.THREADING_ENABLED) {
|
if (areThreadMessagesEnabled) {
|
||||||
threadDetails?.let {
|
threadDetails?.let {
|
||||||
if (it.isRootThread) {
|
if (it.isRootThread) {
|
||||||
showThreadSummary(holder)
|
showThreadSummary(holder)
|
||||||
|
|
|
@ -447,7 +447,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
private fun canReplyInThread(event: TimelineEvent,
|
private fun canReplyInThread(event: TimelineEvent,
|
||||||
messageContent: MessageContent?,
|
messageContent: MessageContent?,
|
||||||
actionPermissions: ActionPermissions): Boolean {
|
actionPermissions: ActionPermissions): Boolean {
|
||||||
if (!BuildConfig.THREADING_ENABLED) return false
|
if (!vectorPreferences.areThreadMessagesEnabled()) return false
|
||||||
if (initialState.isFromThreadTimeline) return false
|
if (initialState.isFromThreadTimeline) return false
|
||||||
if (event.root.getClearType() != EventType.MESSAGE &&
|
if (event.root.getClearType() != EventType.MESSAGE &&
|
||||||
!event.isSticker() && !event.isPoll()) return false
|
!event.isSticker() && !event.isPoll()) return false
|
||||||
|
@ -472,7 +472,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
private fun canViewInRoom(event: TimelineEvent,
|
private fun canViewInRoom(event: TimelineEvent,
|
||||||
messageContent: MessageContent?,
|
messageContent: MessageContent?,
|
||||||
actionPermissions: ActionPermissions): Boolean {
|
actionPermissions: ActionPermissions): Boolean {
|
||||||
if (!BuildConfig.THREADING_ENABLED) return false
|
if (!vectorPreferences.areThreadMessagesEnabled()) return false
|
||||||
if (!initialState.isFromThreadTimeline) return false
|
if (!initialState.isFromThreadTimeline) return false
|
||||||
if (event.root.getClearType() != EventType.MESSAGE &&
|
if (event.root.getClearType() != EventType.MESSAGE &&
|
||||||
!event.isSticker() && !event.isPoll()) return false
|
!event.isSticker() && !event.isPoll()) return false
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.timeline.helper
|
||||||
import im.vector.app.EmojiCompatFontProvider
|
import im.vector.app.EmojiCompatFontProvider
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.core.resources.UserPreferencesProvider
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
|
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
|
||||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||||
|
@ -31,6 +32,7 @@ class MessageItemAttributesFactory @Inject constructor(
|
||||||
private val messageColorProvider: MessageColorProvider,
|
private val messageColorProvider: MessageColorProvider,
|
||||||
private val avatarSizeProvider: AvatarSizeProvider,
|
private val avatarSizeProvider: AvatarSizeProvider,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
|
private val preferencesProvider: UserPreferencesProvider,
|
||||||
private val emojiCompatFontProvider: EmojiCompatFontProvider) {
|
private val emojiCompatFontProvider: EmojiCompatFontProvider) {
|
||||||
|
|
||||||
fun create(messageContent: Any?,
|
fun create(messageContent: Any?,
|
||||||
|
@ -57,7 +59,8 @@ class MessageItemAttributesFactory @Inject constructor(
|
||||||
readReceiptsCallback = callback,
|
readReceiptsCallback = callback,
|
||||||
emojiTypeFace = emojiCompatFontProvider.typeface,
|
emojiTypeFace = emojiCompatFontProvider.typeface,
|
||||||
decryptionErrorMessage = stringProvider.getString(R.string.encrypted_message),
|
decryptionErrorMessage = stringProvider.getString(R.string.encrypted_message),
|
||||||
threadDetails = threadDetails
|
threadDetails = threadDetails,
|
||||||
|
areThreadMessagesEnabled = preferencesProvider.areThreadMessagesEnabled()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,12 +152,11 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BuildConfig.THREADING_ENABLED && !isFromThreadTimeline && root.isThread()) {
|
if (userPreferencesProvider.areThreadMessagesEnabled() && !isFromThreadTimeline && root.isThread()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BuildConfig.THREADING_ENABLED && isFromThreadTimeline) {
|
if (userPreferencesProvider.areThreadMessagesEnabled() && isFromThreadTimeline) {
|
||||||
// //
|
|
||||||
return if (root.getRootThreadEventId() == rootThreadEventId) {
|
return if (root.getRootThreadEventId() == rootThreadEventId) {
|
||||||
false
|
false
|
||||||
} else root.eventId != rootThreadEventId
|
} else root.eventId != rootThreadEventId
|
||||||
|
|
|
@ -113,7 +113,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
||||||
holder.eventSendingIndicator.isVisible = attributes.informationData.sendStateDecoration == SendStateDecoration.SENDING_MEDIA
|
holder.eventSendingIndicator.isVisible = attributes.informationData.sendStateDecoration == SendStateDecoration.SENDING_MEDIA
|
||||||
|
|
||||||
// Threads
|
// Threads
|
||||||
if (BuildConfig.THREADING_ENABLED) {
|
if (attributes.areThreadMessagesEnabled) {
|
||||||
holder.threadSummaryConstraintLayout.onClick(_threadClickListener)
|
holder.threadSummaryConstraintLayout.onClick(_threadClickListener)
|
||||||
attributes.threadDetails?.let { threadDetails ->
|
attributes.threadDetails?.let { threadDetails ->
|
||||||
holder.threadSummaryConstraintLayout.isVisible = threadDetails.isRootThread
|
holder.threadSummaryConstraintLayout.isVisible = threadDetails.isRootThread
|
||||||
|
@ -186,7 +186,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
||||||
override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null,
|
override val readReceiptsCallback: TimelineEventController.ReadReceiptsCallback? = null,
|
||||||
val emojiTypeFace: Typeface? = null,
|
val emojiTypeFace: Typeface? = null,
|
||||||
val decryptionErrorMessage: String? = null,
|
val decryptionErrorMessage: String? = null,
|
||||||
val threadDetails: ThreadDetails? = null
|
val threadDetails: ThreadDetails? = null,
|
||||||
|
val areThreadMessagesEnabled: Boolean = false
|
||||||
) : AbsBaseMessageItem.Attributes {
|
) : AbsBaseMessageItem.Attributes {
|
||||||
|
|
||||||
// Have to override as it's used to diff epoxy items
|
// Have to override as it's used to diff epoxy items
|
||||||
|
|
|
@ -197,6 +197,7 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||||
private const val TAKE_PHOTO_VIDEO_MODE = "TAKE_PHOTO_VIDEO_MODE"
|
private const val TAKE_PHOTO_VIDEO_MODE = "TAKE_PHOTO_VIDEO_MODE"
|
||||||
|
|
||||||
private const val SETTINGS_LABS_ENABLE_POLLS = "SETTINGS_LABS_ENABLE_POLLS"
|
private const val SETTINGS_LABS_ENABLE_POLLS = "SETTINGS_LABS_ENABLE_POLLS"
|
||||||
|
const val SETTINGS_LABS_ENABLE_THREAD_MESSAGES = "SETTINGS_LABS_ENABLE_THREAD_MESSAGES"
|
||||||
|
|
||||||
// Possible values for TAKE_PHOTO_VIDEO_MODE
|
// Possible values for TAKE_PHOTO_VIDEO_MODE
|
||||||
const val TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK = 0
|
const val TAKE_PHOTO_VIDEO_MODE_ALWAYS_ASK = 0
|
||||||
|
@ -995,4 +996,8 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||||
fun labsEnablePolls(): Boolean {
|
fun labsEnablePolls(): Boolean {
|
||||||
return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_POLLS, false)
|
return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_POLLS, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun areThreadMessagesEnabled(): Boolean {
|
||||||
|
return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_THREAD_MESSAGES, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings
|
package im.vector.app.features.settings
|
||||||
|
|
||||||
|
import androidx.preference.Preference
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.preference.VectorSwitchPreference
|
import im.vector.app.core.preference.VectorSwitchPreference
|
||||||
|
import im.vector.app.features.MainActivity
|
||||||
|
import im.vector.app.features.MainActivityArgs
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class VectorSettingsLabsFragment @Inject constructor(
|
class VectorSettingsLabsFragment @Inject constructor(
|
||||||
|
@ -32,5 +35,15 @@ class VectorSettingsLabsFragment @Inject constructor(
|
||||||
// ensure correct default
|
// ensure correct default
|
||||||
pref.isChecked = vectorPreferences.labsAutoReportUISI()
|
pref.isChecked = vectorPreferences.labsAutoReportUISI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear cache
|
||||||
|
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let {
|
||||||
|
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
displayLoadingView()
|
||||||
|
MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true))
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3600,6 +3600,8 @@
|
||||||
|
|
||||||
<string name="labs_auto_report_uisi">Auto Report Decryption Errors.</string>
|
<string name="labs_auto_report_uisi">Auto Report Decryption Errors.</string>
|
||||||
<string name="labs_auto_report_uisi_desc">Your system will automatically send logs when an unable to decrypt error occurs</string>
|
<string name="labs_auto_report_uisi_desc">Your system will automatically send logs when an unable to decrypt error occurs</string>
|
||||||
|
<string name="labs_enable_thread_messages">Enable Thread Messages</string>
|
||||||
|
<string name="labs_enable_thread_messages_desc">Note: app will be restarted</string>
|
||||||
|
|
||||||
<string name="user_invites_you">%s invites you</string>
|
<string name="user_invites_you">%s invites you</string>
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,16 @@
|
||||||
android:key="SETTINGS_LABS_ENABLE_POLLS"
|
android:key="SETTINGS_LABS_ENABLE_POLLS"
|
||||||
android:title="@string/labs_enable_polls" />
|
android:title="@string/labs_enable_polls" />
|
||||||
|
|
||||||
|
<im.vector.app.core.preference.VectorSwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="SETTINGS_LABS_ENABLE_THREAD_MESSAGES"
|
||||||
|
android:summary="@string/labs_enable_thread_messages_desc"
|
||||||
|
android:title="@string/labs_enable_thread_messages" />
|
||||||
|
|
||||||
<im.vector.app.core.preference.VectorSwitchPreference
|
<im.vector.app.core.preference.VectorSwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="SETTINGS_LABS_AUTO_REPORT_UISI"
|
android:key="SETTINGS_LABS_AUTO_REPORT_UISI"
|
||||||
android:title="@string/labs_auto_report_uisi"
|
android:summary="@string/labs_auto_report_uisi_desc"
|
||||||
android:summary="@string/labs_auto_report_uisi_desc"/>
|
android:title="@string/labs_auto_report_uisi" />
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
Loading…
Reference in a new issue