Add LightweightSettingsStorage in sdk

Enable thread awareness when threads are disabled
Enhance enable/disable thread messages to app & sdk
Add Shared PReferences to sdk
This commit is contained in:
ariskotsomitopoulos 2022-01-19 18:52:02 +02:00
parent 8cc96e27bc
commit 38f193fbd5
17 changed files with 115 additions and 46 deletions

View file

@ -141,6 +141,9 @@ dependencies {
kapt 'dk.ilios:realmfieldnameshelper:2.0.0'
// Shared Preferences
implementation libs.androidx.preferenceKtx
// Work
implementation libs.androidx.work

View file

@ -96,11 +96,6 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
companion object {
/**
* Determines whether or not thread messages are enabled
*/
var areThreadMessagesEnabled: Boolean = false
private lateinit var instance: Matrix
private val isInit = AtomicBoolean(false)

View file

@ -21,5 +21,6 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class ReplyToContent(
@Json(name = "event_id") val eventId: String? = null
@Json(name = "event_id") val eventId: String? = null,
@Json(name = "render_in") val renderIn: List<String>? = null
)

View file

@ -0,0 +1,47 @@
/*
* Copyright 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.
* 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.database.lightweight
import android.content.Context
import androidx.core.content.edit
import androidx.preference.PreferenceManager
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
* not for large data sets
*/
class LightweightSettingsStorage @Inject constructor(context: Context) {
private val sdkDefaultPrefs = PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
fun setThreadMessagesEnabled(enabled: Boolean) {
sdkDefaultPrefs.edit {
putBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, enabled)
}
}
fun areThreadMessagesEnabled(): Boolean {
return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, false)
}
companion object {
const val MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED = "MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED"
}
}

View file

@ -471,8 +471,8 @@ internal class LocalEchoEventFactory @Inject constructor(
RelationDefaultContent(
type = RelationType.IO_THREAD,
eventId = it,
inReplyTo = ReplyToContent(eventId))
} ?: RelationDefaultContent(null, null, ReplyToContent(eventId))
inReplyTo = ReplyToContent(eventId = eventId))
} ?: RelationDefaultContent(null, null, ReplyToContent( eventId = eventId))
private fun buildFormattedReply(permalink: String, userLink: String, userId: String, bodyFormatted: String, newBodyFormatted: String): String {
return REPLY_PATTERN.format(

View file

@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromHtmlReply
import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply
@ -48,7 +49,7 @@ fun TextContent.toThreadTextContent(rootThreadEventId: String, msgType: String =
msgType = msgType,
format = MessageFormat.FORMAT_MATRIX_HTML.takeIf { formattedText != null },
body = text,
relatesTo = RelationDefaultContent(RelationType.IO_THREAD, rootThreadEventId),
relatesTo = RelationDefaultContent(type = RelationType.IO_THREAD, eventId = rootThreadEventId, inReplyTo = ReplyToContent(eventId = "CYIpEhDXkImqKD2TF9NSocxt4vU6hh98yXi5Ncusdaw")),
formattedBody = formattedText
)
}

View file

@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler
@ -60,6 +61,7 @@ internal class DefaultTimeline(private val roomId: String,
timelineEventMapper: TimelineEventMapper,
timelineInput: TimelineInput,
threadsAwarenessHandler: ThreadsAwarenessHandler,
lightweightSettingsStorage: LightweightSettingsStorage,
eventDecryptor: TimelineEventDecryptor) : Timeline {
companion object {
@ -92,6 +94,7 @@ internal class DefaultTimeline(private val roomId: String,
timelineInput = timelineInput,
timelineEventMapper = timelineEventMapper,
threadsAwarenessHandler = threadsAwarenessHandler,
lightweightSettingsStorage = lightweightSettingsStorage,
onEventsUpdated = this::sendSignalToPostSnapshot,
onLimitedTimeline = this::onLimitedTimeline,
onNewTimelineEvents = this::onNewTimelineEvents

View file

@ -37,6 +37,7 @@ import org.matrix.android.sdk.internal.database.RealmSessionProvider
import org.matrix.android.sdk.internal.database.helper.findAllLocalThreadNotificationsForRoomId
import org.matrix.android.sdk.internal.database.helper.findAllThreadsForRoomId
import org.matrix.android.sdk.internal.database.helper.isUserParticipatingInThread
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
import org.matrix.android.sdk.internal.database.model.EventEntity
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
@ -64,6 +65,7 @@ internal class DefaultTimelineService @AssistedInject constructor(
private val timelineEventMapper: TimelineEventMapper,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val readReceiptHandler: ReadReceiptHandler,
private val coroutineDispatchers: MatrixCoroutineDispatchers
) : TimelineService {
@ -88,7 +90,8 @@ internal class DefaultTimelineService @AssistedInject constructor(
loadRoomMembersTask = loadRoomMembersTask,
readReceiptHandler = readReceiptHandler,
getEventTask = contextOfEventTask,
threadsAwarenessHandler = threadsAwarenessHandler
threadsAwarenessHandler = threadsAwarenessHandler,
lightweightSettingsStorage = lightweightSettingsStorage
)
}

View file

@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
import org.matrix.android.sdk.internal.database.model.ChunkEntity
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
@ -80,6 +81,7 @@ internal class LoadTimelineStrategy(
val timelineInput: TimelineInput,
val timelineEventMapper: TimelineEventMapper,
val threadsAwarenessHandler: ThreadsAwarenessHandler,
val lightweightSettingsStorage: LightweightSettingsStorage,
val onEventsUpdated: (Boolean) -> Unit,
val onLimitedTimeline: () -> Unit,
val onNewTimelineEvents: (List<String>) -> Unit
@ -241,6 +243,7 @@ internal class LoadTimelineStrategy(
timelineEventMapper = dependencies.timelineEventMapper,
uiEchoManager = uiEchoManager,
threadsAwarenessHandler = dependencies.threadsAwarenessHandler,
lightweightSettingsStorage = dependencies.lightweightSettingsStorage,
initialEventId = mode.originEventId(),
onBuiltEvents = dependencies.onEventsUpdated
)

View file

@ -23,13 +23,13 @@ import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import kotlinx.coroutines.CompletableDeferred
import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.EventMapper
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
import org.matrix.android.sdk.internal.database.model.ChunkEntity
@ -56,6 +56,7 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
private val timelineEventMapper: TimelineEventMapper,
private val uiEchoManager: UIEchoManager? = null,
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val initialEventId: String?,
private val onBuiltEvents: (Boolean) -> Unit) {
@ -296,7 +297,9 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
if (timelineEvents.isEmpty()) return LoadedFromStorage()
// Disabled due to the new fallback
// fetchRootThreadEventsIfNeeded(timelineEvents)
if(!lightweightSettingsStorage.areThreadMessagesEnabled()) {
fetchRootThreadEventsIfNeeded(timelineEvents)
}
if (direction == Timeline.Direction.FORWARDS) {
builtEventsIndexes.entries.forEach { it.setValue(it.value + timelineEvents.size) }
}
@ -333,7 +336,6 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
* in order to be able to display the event to the user appropriately
*/
private suspend fun fetchRootThreadEventsIfNeeded(offsetResults: List<TimelineEventEntity>) {
// if (BuildConfig.THREADING_ENABLED) return
val eventEntityList = offsetResults
.mapNotNull {
it.root
@ -486,6 +488,7 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
timelineEventMapper = timelineEventMapper,
uiEchoManager = uiEchoManager,
threadsAwarenessHandler = threadsAwarenessHandler,
lightweightSettingsStorage = lightweightSettingsStorage,
initialEventId = null,
onBuiltEvents = this.onBuiltEvents
)

View file

@ -17,13 +17,13 @@ package org.matrix.android.sdk.internal.session.room.timeline
import io.realm.Realm
import io.realm.RealmConfiguration
import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.session.crypto.CryptoService
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.toModel
import org.matrix.android.sdk.internal.crypto.NewSessionListener
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.model.EventEntity
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase
@ -37,7 +37,8 @@ internal class TimelineEventDecryptor @Inject constructor(
@SessionDatabase
private val realmConfiguration: RealmConfiguration,
private val cryptoService: CryptoService,
private val threadsAwarenessHandler: ThreadsAwarenessHandler
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
private val lightweightSettingsStorage: LightweightSettingsStorage
) {
private val newSessionListener = object : NewSessionListener {
@ -117,15 +118,15 @@ internal class TimelineEventDecryptor @Inject constructor(
eventEntity?.apply {
val decryptedPayload =
// Disabled due to the new fallback
// if (!BuildConfig.THREADING_ENABLED) {
// threadsAwarenessHandler.handleIfNeededDuringDecryption(
// it,
// roomId = event.roomId,
// event,
// result)
// } else {
if (!lightweightSettingsStorage.areThreadMessagesEnabled()) {
threadsAwarenessHandler.handleIfNeededDuringDecryption(
it,
roomId = event.roomId,
event,
result)
} else {
null
// }
}
setDecryptionResult(result, decryptedPayload)
}
}

View file

@ -19,8 +19,6 @@ package org.matrix.android.sdk.internal.session.room.timeline
import com.zhuinden.monarchy.Monarchy
import dagger.Lazy
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.toModel
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
@ -29,6 +27,7 @@ import org.matrix.android.sdk.internal.database.helper.addIfNecessary
import org.matrix.android.sdk.internal.database.helper.addStateEvent
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
import org.matrix.android.sdk.internal.database.helper.updateThreadSummaryIfNeeded
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.toEntity
import org.matrix.android.sdk.internal.database.model.ChunkEntity
import org.matrix.android.sdk.internal.database.model.EventEntity
@ -52,7 +51,7 @@ import javax.inject.Inject
internal class TokenChunkEventPersistor @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
@UserId private val userId: String,
private val matrixConfiguration: MatrixConfiguration,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val liveEventManager: Lazy<StreamEventsManager>) {
enum class Result {
@ -185,7 +184,7 @@ internal class TokenChunkEventPersistor @Inject constructor(
}
liveEventManager.get().dispatchPaginatedEventReceived(event, roomId)
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser)
if(Matrix.areThreadMessagesEnabled) {
if(lightweightSettingsStorage.areThreadMessagesEnabled()) {
eventEntity.rootThreadEventId?.let {
// This is a thread event
optimizedThreadSummaryMap[it] = eventEntity
@ -199,7 +198,8 @@ internal class TokenChunkEventPersistor @Inject constructor(
if (currentChunk.isValid) {
RoomEntity.where(realm, roomId).findFirst()?.addIfNecessary(currentChunk)
}
if(Matrix.areThreadMessagesEnabled) {
if(lightweightSettingsStorage.areThreadMessagesEnabled()) {
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(roomId = roomId, realm = realm, currentUserId = userId)
}
}

View file

@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.sync
import androidx.work.ExistingPeriodicWorkPolicy
import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.BuildConfig
import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.pushrules.RuleScope
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
@ -27,6 +26,7 @@ import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
import org.matrix.android.sdk.api.session.sync.model.SyncResponse
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.WorkManagerProvider
@ -65,6 +65,7 @@ internal class SyncResponseHandler @Inject constructor(
private val aggregatorHandler: SyncResponsePostTreatmentAggregatorHandler,
private val cryptoService: DefaultCryptoService,
private val tokenStore: SyncTokenStore,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val processEventForPushTask: ProcessEventForPushTask,
private val pushRuleService: PushRuleService,
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
@ -103,9 +104,9 @@ internal class SyncResponseHandler @Inject constructor(
// Prerequisite for thread events handling in RoomSyncHandler
// Disabled due to the new fallback
// if (!BuildConfig.THREADING_ENABLED) {
// threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(syncResponse)
// }
if (!lightweightSettingsStorage.areThreadMessagesEnabled()) {
threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(syncResponse)
}
// Start one big transaction
monarchy.awaitTransaction { realm ->

View file

@ -19,8 +19,6 @@ package org.matrix.android.sdk.internal.session.sync.handler.room
import dagger.Lazy
import io.realm.Realm
import io.realm.kotlin.createObject
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.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
@ -39,6 +37,7 @@ import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
import org.matrix.android.sdk.internal.database.helper.updateThreadSummaryIfNeeded
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.mapper.toEntity
import org.matrix.android.sdk.internal.database.model.ChunkEntity
@ -83,9 +82,9 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
private val roomMemberEventHandler: RoomMemberEventHandler,
private val roomTypingUsersHandler: RoomTypingUsersHandler,
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
private val matrixConfiguration: MatrixConfiguration,
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
@UserId private val userId: String,
private val lightweightSettingsStorage: LightweightSettingsStorage,
private val timelineInput: TimelineInput,
private val liveEventService: Lazy<StreamEventsManager>) {
@ -373,6 +372,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
if (event.eventId == null || event.senderId == null || event.type == null) {
continue
}
eventIds.add(event.eventId)
liveEventService.get().dispatchLiveEventReceived(event, roomId, insertType == EventInsertType.INITIAL_SYNC)
@ -382,12 +382,12 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
decryptIfNeeded(event, roomId)
}
// Disabled due to the new fallback
// if (!BuildConfig.THREADING_ENABLED) {
// threadsAwarenessHandler.handleIfNeeded(
// realm = realm,
// roomId = roomId,
// event = event)
// }
if (!lightweightSettingsStorage.areThreadMessagesEnabled()) {
threadsAwarenessHandler.handleIfNeeded(
realm = realm,
roomId = roomId,
event = event)
}
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
val eventEntity = event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, insertType)
@ -410,7 +410,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
}
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser)
if(Matrix.areThreadMessagesEnabled) {
if(lightweightSettingsStorage.areThreadMessagesEnabled()) {
eventEntity.rootThreadEventId?.let {
// This is a thread event
optimizedThreadSummaryMap[it] = eventEntity
@ -446,7 +446,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
}
// Handle deletion of [stuck] local echos if needed
deleteLocalEchosIfNeeded(insertType, roomEntity, eventList)
if(Matrix.areThreadMessagesEnabled) {
if(lightweightSettingsStorage.areThreadMessagesEnabled()) {
optimizedThreadSummaryMap.updateThreadSummaryIfNeeded(
roomId = roomId,
realm = realm,

View file

@ -45,6 +45,7 @@ import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
import org.matrix.android.sdk.internal.session.room.timeline.GetEventTask
import org.matrix.android.sdk.internal.util.awaitTransaction
import timber.log.Timber
import javax.inject.Inject
/**
@ -280,6 +281,9 @@ internal class ThreadsAwarenessHandler @Inject constructor(
*/
private fun getRootThreadEventId(event: Event): String? =
event.content.toModel<MessageRelationContent>()?.relatesTo?.eventId
// private fun getRootThreadEventId(event: Event): String? =
// event.content.toModel<MessageRelationContent>()?.relatesTo?.inReplyTo?.eventId ?:
// event.content.toModel<MessageRelationContent>()?.relatesTo?.eventId
@Suppress("UNCHECKED_CAST")
private fun getValueFromPayload(payload: JsonDict?, key: String): String? {

View file

@ -194,7 +194,6 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
navigator = singletonEntryPoint.navigator()
activeSessionHolder = singletonEntryPoint.activeSessionHolder()
vectorPreferences = singletonEntryPoint.vectorPreferences()
Matrix.areThreadMessagesEnabled = vectorPreferences.areThreadMessagesEnabled()
configurationViewModel.activityRestarter.observe(this) {
if (!it.hasBeenHandled) {
// Recreate the Activity because configuration has changed

View file

@ -21,10 +21,13 @@ 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 org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
import javax.inject.Inject
class VectorSettingsLabsFragment @Inject constructor(
private val vectorPreferences: VectorPreferences
private val vectorPreferences: VectorPreferences,
private val lightweightSettingsStorage: LightweightSettingsStorage
) : VectorSettingsBaseFragment() {
override var titleRes = R.string.room_settings_labs_pref_title
@ -38,7 +41,8 @@ class VectorSettingsLabsFragment @Inject constructor(
// clear cache
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let {
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
it.onPreferenceClickListener = Preference.OnPreferenceClickListener { pref->
lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled())
displayLoadingView()
MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true))
false