mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-21 17:05:39 +03:00
Add a setting to be able to always appear offline (#5583)
Add a setting to be able to always appear offline Move presence enabling to a app-only preference
This commit is contained in:
parent
454a65602b
commit
047a45d77f
18 changed files with 116 additions and 46 deletions
1
changelog.d/5582.feature
Normal file
1
changelog.d/5582.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Add a setting to be able to always appear offline
|
|
@ -61,10 +61,6 @@ data class MatrixConfiguration(
|
|||
* RoomDisplayNameFallbackProvider to provide default room display name.
|
||||
*/
|
||||
val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider,
|
||||
/**
|
||||
* True to enable presence information sync (if available). False to disable regardless of server setting.
|
||||
*/
|
||||
val presenceSyncEnabled: Boolean = true,
|
||||
/**
|
||||
* Thread messages default enable/disabled value
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context
|
|||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncPresence
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -45,7 +46,29 @@ class LightweightSettingsStorage @Inject constructor(
|
|||
return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, matrixConfiguration.threadMessagesEnabledDefault)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the presence status sent on syncs when the application is in foreground.
|
||||
*
|
||||
* @param presence the presence status that should be sent on sync
|
||||
*/
|
||||
internal fun setSyncPresenceStatus(presence: SyncPresence) {
|
||||
sdkDefaultPrefs.edit {
|
||||
putString(MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS, presence.value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presence status that should be sent on syncs when the application is in foreground.
|
||||
*
|
||||
* @return the presence status that should be sent on sync
|
||||
*/
|
||||
internal fun getSyncPresenceStatus(): SyncPresence {
|
||||
val presenceString = sdkDefaultPrefs.getString(MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS, SyncPresence.Online.value)
|
||||
return SyncPresence.from(presenceString) ?: SyncPresence.Online
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED = "MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED"
|
||||
private const val MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS = "MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,18 +20,22 @@ package org.matrix.android.sdk.internal.session.presence.service
|
|||
import org.matrix.android.sdk.api.session.presence.PresenceService
|
||||
import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
|
||||
import org.matrix.android.sdk.api.session.presence.model.UserPresence
|
||||
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.presence.service.task.GetPresenceTask
|
||||
import org.matrix.android.sdk.internal.session.presence.service.task.SetPresenceTask
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncPresence
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultPresenceService @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
private val setPresenceTask: SetPresenceTask,
|
||||
private val getPresenceTask: GetPresenceTask
|
||||
private val getPresenceTask: GetPresenceTask,
|
||||
private val lightweightSettingsStorage: LightweightSettingsStorage
|
||||
) : PresenceService {
|
||||
|
||||
override suspend fun setMyPresence(presence: PresenceEnum, statusMsg: String?) {
|
||||
lightweightSettingsStorage.setSyncPresenceStatus(SyncPresence.from(presence))
|
||||
setPresenceTask.execute(SetPresenceTask.Params(userId, presence, statusMsg))
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.sync
|
||||
|
||||
import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
|
||||
|
||||
/**
|
||||
* For `set_presence` parameter in the /sync request
|
||||
*
|
||||
|
@ -27,5 +29,16 @@ package org.matrix.android.sdk.internal.session.sync
|
|||
enum class SyncPresence(val value: String) {
|
||||
Offline("offline"),
|
||||
Online("online"),
|
||||
Unavailable("unavailable")
|
||||
Unavailable("unavailable");
|
||||
|
||||
companion object {
|
||||
fun from(presenceEnum: PresenceEnum): SyncPresence {
|
||||
return when (presenceEnum) {
|
||||
PresenceEnum.ONLINE -> Online
|
||||
PresenceEnum.OFFLINE -> Offline
|
||||
PresenceEnum.UNAVAILABLE -> Unavailable
|
||||
}
|
||||
}
|
||||
fun from(s: String?): SyncPresence? = values().find { it.value == s }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,26 +31,24 @@ import javax.inject.Inject
|
|||
internal class PresenceSyncHandler @Inject constructor(private val matrixConfiguration: MatrixConfiguration) {
|
||||
|
||||
fun handle(realm: Realm, presenceSyncResponse: PresenceSyncResponse?) {
|
||||
if (matrixConfiguration.presenceSyncEnabled) {
|
||||
presenceSyncResponse?.events
|
||||
?.filter { event -> event.type == EventType.PRESENCE }
|
||||
?.forEach { event ->
|
||||
val content = event.getPresenceContent() ?: return@forEach
|
||||
val userId = event.senderId ?: return@forEach
|
||||
val userPresenceEntity = UserPresenceEntity(
|
||||
userId = userId,
|
||||
lastActiveAgo = content.lastActiveAgo,
|
||||
statusMessage = content.statusMessage,
|
||||
isCurrentlyActive = content.isCurrentlyActive,
|
||||
avatarUrl = content.avatarUrl,
|
||||
displayName = content.displayName
|
||||
).also {
|
||||
it.presence = content.presence
|
||||
}
|
||||
|
||||
storePresenceToDB(realm, userPresenceEntity)
|
||||
presenceSyncResponse?.events
|
||||
?.filter { event -> event.type == EventType.PRESENCE }
|
||||
?.forEach { event ->
|
||||
val content = event.getPresenceContent() ?: return@forEach
|
||||
val userId = event.senderId ?: return@forEach
|
||||
val userPresenceEntity = UserPresenceEntity(
|
||||
userId = userId,
|
||||
lastActiveAgo = content.lastActiveAgo,
|
||||
statusMessage = content.statusMessage,
|
||||
isCurrentlyActive = content.isCurrentlyActive,
|
||||
avatarUrl = content.avatarUrl,
|
||||
displayName = content.displayName
|
||||
).also {
|
||||
it.presence = content.presence
|
||||
}
|
||||
}
|
||||
|
||||
storePresenceToDB(realm, userPresenceEntity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,9 +37,9 @@ import org.matrix.android.sdk.api.logger.LoggerTag
|
|||
import org.matrix.android.sdk.api.session.call.MxCall
|
||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||
import org.matrix.android.sdk.api.session.sync.model.SyncResponse
|
||||
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
|
||||
import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker
|
||||
import org.matrix.android.sdk.internal.session.call.ActiveCallHandler
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncPresence
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncTask
|
||||
import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
|
||||
import org.matrix.android.sdk.internal.util.Debouncer
|
||||
|
@ -59,7 +59,8 @@ private val loggerTag = LoggerTag("SyncThread", LoggerTag.SYNC)
|
|||
internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
|
||||
private val networkConnectivityChecker: NetworkConnectivityChecker,
|
||||
private val backgroundDetectionObserver: BackgroundDetectionObserver,
|
||||
private val activeCallHandler: ActiveCallHandler
|
||||
private val activeCallHandler: ActiveCallHandler,
|
||||
private val lightweightSettingsStorage: LightweightSettingsStorage
|
||||
) : Thread("SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
|
||||
|
||||
private var state: SyncState = SyncState.Idle
|
||||
|
@ -182,7 +183,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
|
|||
else -> DEFAULT_LONG_POOL_TIMEOUT
|
||||
}
|
||||
Timber.tag(loggerTag.value).d("Execute sync request with timeout $timeout")
|
||||
val params = SyncTask.Params(timeout, SyncPresence.Online, afterPause = afterPause)
|
||||
val presence = lightweightSettingsStorage.getSyncPresenceStatus()
|
||||
val params = SyncTask.Params(timeout, presence, afterPause = afterPause)
|
||||
val sync = syncScope.launch {
|
||||
previousSyncResponseHasToDevice = doSync(params)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
<bool name="settings_interface_bubble_visible">true</bool>
|
||||
<bool name="settings_interface_bubble_default">false</bool>
|
||||
<bool name="settings_presence_visible">false</bool>
|
||||
<bool name="settings_presence_user_always_appears_offline_default">false</bool>
|
||||
|
||||
<!-- Level 1: Voice and video -->
|
||||
|
||||
|
|
|
@ -151,7 +151,6 @@ android {
|
|||
|
||||
buildConfigField "Boolean", "enableLocationSharing", "true"
|
||||
buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\""
|
||||
buildConfigField "Boolean", "PRESENCE_SYNC_ENABLED", "true"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -121,7 +121,6 @@ object VectorStaticModule {
|
|||
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
|
||||
roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider,
|
||||
threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(),
|
||||
presenceSyncEnabled = BuildConfig.PRESENCE_SYNC_ENABLED
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,6 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import org.billcarsonfr.jsonviewer.JSonViewerDialog
|
||||
import org.commonmark.parser.Parser
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
|
@ -266,8 +265,7 @@ class TimelineFragment @Inject constructor(
|
|||
private val pillsPostProcessorFactory: PillsPostProcessor.Factory,
|
||||
private val callManager: WebRtcCallManager,
|
||||
private val audioMessagePlaybackTracker: AudioMessagePlaybackTracker,
|
||||
private val clock: Clock,
|
||||
private val matrixConfiguration: MatrixConfiguration
|
||||
private val clock: Clock
|
||||
) :
|
||||
VectorBaseFragment<FragmentTimelineBinding>(),
|
||||
TimelineEventController.Callback,
|
||||
|
@ -1650,7 +1648,7 @@ class TimelineFragment @Inject constructor(
|
|||
views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
|
||||
views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName
|
||||
avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView)
|
||||
val showPresence = roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled
|
||||
val showPresence = roomSummary.isDirect
|
||||
views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence)
|
||||
val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield
|
||||
shieldView.render(roomSummary.roomEncryptionTrustLevel)
|
||||
|
|
|
@ -29,7 +29,6 @@ import im.vector.app.features.home.AvatarRenderer
|
|||
import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter
|
||||
import im.vector.app.features.home.room.typing.TypingHelper
|
||||
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -42,8 +41,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
|||
private val stringProvider: StringProvider,
|
||||
private val typingHelper: TypingHelper,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val errorFormatter: ErrorFormatter,
|
||||
private val matrixConfiguration: MatrixConfiguration) {
|
||||
private val errorFormatter: ErrorFormatter) {
|
||||
|
||||
fun create(roomSummary: RoomSummary,
|
||||
roomChangeMembershipStates: Map<String, ChangeMembershipState>,
|
||||
|
@ -127,7 +125,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
|||
// We do not display shield in the room list anymore
|
||||
// .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel)
|
||||
.izPublic(roomSummary.isPublic)
|
||||
.showPresence(roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled)
|
||||
.showPresence(roomSummary.isDirect)
|
||||
.userPresence(roomSummary.directUserPresence)
|
||||
.matrixItem(roomSummary.toMatrixItem())
|
||||
.lastEventTime(latestEventTime)
|
||||
|
|
|
@ -54,7 +54,6 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
|
|||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import timber.log.Timber
|
||||
|
@ -69,7 +68,6 @@ class RoomProfileFragment @Inject constructor(
|
|||
private val roomProfileController: RoomProfileController,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
|
||||
private val matrixConfiguration: MatrixConfiguration
|
||||
) :
|
||||
VectorBaseFragment<FragmentMatrixProfileBinding>(),
|
||||
RoomProfileController.Callback {
|
||||
|
@ -224,7 +222,7 @@ class RoomProfileFragment @Inject constructor(
|
|||
avatarRenderer.render(matrixItem, views.matrixProfileToolbarAvatarImageView)
|
||||
headerViews.roomProfileDecorationImageView.render(it.roomEncryptionTrustLevel)
|
||||
views.matrixProfileDecorationToolbarAvatarImageView.render(it.roomEncryptionTrustLevel)
|
||||
headerViews.roomProfilePresenceImageView.render(it.isDirect && matrixConfiguration.presenceSyncEnabled, it.directUserPresence)
|
||||
headerViews.roomProfilePresenceImageView.render(it.isDirect, it.directUserPresence)
|
||||
headerViews.roomProfilePublicImageView.isVisible = it.isPublic && !it.isDirect
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import im.vector.app.core.resources.ColorProvider
|
|||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import me.gujun.android.span.span
|
||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||
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.api.session.room.model.RoomMemberSummary
|
||||
|
@ -40,8 +39,7 @@ class RoomMemberListController @Inject constructor(
|
|||
private val avatarRenderer: AvatarRenderer,
|
||||
private val stringProvider: StringProvider,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val roomMemberSummaryFilter: RoomMemberSummaryFilter,
|
||||
private val matrixConfiguration: MatrixConfiguration
|
||||
private val roomMemberSummaryFilter: RoomMemberSummaryFilter
|
||||
) : TypedEpoxyController<RoomMemberListViewState>() {
|
||||
|
||||
interface Callback {
|
||||
|
@ -124,7 +122,6 @@ class RoomMemberListController @Inject constructor(
|
|||
host: RoomMemberListController,
|
||||
data: RoomMemberListViewState) {
|
||||
val powerLabel = stringProvider.getString(powerLevelCategory.titleRes)
|
||||
val presenceSyncEnabled = matrixConfiguration.presenceSyncEnabled
|
||||
|
||||
profileMatrixItemWithPowerLevelWithPresence {
|
||||
id(roomMember.userId)
|
||||
|
@ -134,7 +131,7 @@ class RoomMemberListController @Inject constructor(
|
|||
clickListener {
|
||||
host.callback?.onRoomMemberClicked(roomMember)
|
||||
}
|
||||
showPresence(presenceSyncEnabled)
|
||||
showPresence(true)
|
||||
userPresence(roomMember.userPresence)
|
||||
powerLevelLabel(
|
||||
span {
|
||||
|
|
|
@ -100,6 +100,7 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||
private const val SETTINGS_ENABLE_CHAT_EFFECTS = "SETTINGS_ENABLE_CHAT_EFFECTS"
|
||||
private const val SETTINGS_SHOW_EMOJI_KEYBOARD = "SETTINGS_SHOW_EMOJI_KEYBOARD"
|
||||
private const val SETTINGS_LABS_ENABLE_LATEX_MATHS = "SETTINGS_LABS_ENABLE_LATEX_MATHS"
|
||||
const val SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE = "SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE"
|
||||
|
||||
// Room directory
|
||||
private const val SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS = "SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS"
|
||||
|
@ -865,6 +866,16 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||
return defaultPrefs.getBoolean(SETTINGS_INTERFACE_BUBBLE_KEY, getDefault(R.bool.settings_interface_bubble_default))
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if user should always appear offline or not.
|
||||
*
|
||||
* @return true if user should always appear offline
|
||||
*/
|
||||
fun userAlwaysAppearsOffline(): Boolean {
|
||||
return defaultPrefs.getBoolean(SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE,
|
||||
getDefault(R.bool.settings_presence_user_always_appears_offline_default))
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rage shake enabled status.
|
||||
*
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.content.Context
|
|||
import android.os.Bundle
|
||||
import android.widget.CheckedTextView
|
||||
import androidx.core.view.children
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.BuildConfig
|
||||
|
@ -36,6 +37,8 @@ import im.vector.app.features.MainActivityArgs
|
|||
import im.vector.app.features.analytics.plan.MobileScreen
|
||||
import im.vector.app.features.configuration.VectorConfiguration
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
|
||||
import javax.inject.Inject
|
||||
|
||||
class VectorSettingsPreferencesFragment @Inject constructor(
|
||||
|
@ -78,6 +81,17 @@ class VectorSettingsPreferencesFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE)!!.let { pref ->
|
||||
pref.isChecked = vectorPreferences.userAlwaysAppearsOffline()
|
||||
pref.setOnPreferenceChangeListener { _, newValue ->
|
||||
val presenceOfflineModeEnabled = newValue as? Boolean ?: false
|
||||
lifecycleScope.launch {
|
||||
session.setMyPresence(if (presenceOfflineModeEnabled) PresenceEnum.OFFLINE else PresenceEnum.ONLINE)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME)!!.let { pref ->
|
||||
pref.isChecked = vectorPreferences.prefSpacesShowAllRoomInHome()
|
||||
pref.setOnPreferenceChangeListener { _, _ ->
|
||||
|
|
|
@ -1056,6 +1056,11 @@
|
|||
<string name="media_saving_period_1_month">1 month</string>
|
||||
<string name="media_saving_period_forever">Forever</string>
|
||||
|
||||
<!-- Presence settings -->
|
||||
<string name="settings_presence">Presence</string>
|
||||
<string name="settings_presence_user_always_appears_offline">Offline mode</string>
|
||||
<string name="settings_presence_user_always_appears_offline_summary">If enabled, you will always appear offline to other users, even when using the application.</string>
|
||||
|
||||
<!-- Room Settings -->
|
||||
|
||||
<!-- room global settings-->
|
||||
|
|
|
@ -198,6 +198,18 @@
|
|||
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory
|
||||
android:title="@string/settings_presence"
|
||||
app:isPreferenceVisible="@bool/settings_presence_visible">
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:title="@string/settings_presence_user_always_appears_offline"
|
||||
android:summary="@string/settings_presence_user_always_appears_offline_summary"
|
||||
android:key="SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE"
|
||||
android:defaultValue="@bool/settings_presence_user_always_appears_offline_default" />
|
||||
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_category_room_directory">
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
|
|
Loading…
Reference in a new issue