Move setting to room profile
This commit is contained in:
parent
8de2fe8917
commit
68d4ac34c7
|
@ -1236,7 +1236,7 @@
|
||||||
<string name="encryption_never_send_to_unverified_devices_summary">Never send encrypted messages to unverified sessions from this session.</string>
|
<string name="encryption_never_send_to_unverified_devices_summary">Never send encrypted messages to unverified sessions from this session.</string>
|
||||||
<string name="encryption_never_send_to_unverified_devices_in_room">Never send encrypted messages to unverified sessions in this room.</string>
|
<string name="encryption_never_send_to_unverified_devices_in_room">Never send encrypted messages to unverified sessions in this room.</string>
|
||||||
<string name="some_devices_will_not_be_able_to_decrypt">⚠ There are unverified devices in this room, they won’t be able to decrypt messages you send.</string>
|
<string name="some_devices_will_not_be_able_to_decrypt">⚠ There are unverified devices in this room, they won’t be able to decrypt messages you send.</string>
|
||||||
<string name="room_settings_global_blacklist_unverified_info_text">🔒 You have enabled encrypt to verified sessions only for all rooms in Security Settings.</string>
|
<string name="room_settings_global_block_unverified_info_text">🔒 You have enabled encrypt to verified sessions only for all rooms in Security Settings.</string>
|
||||||
<plurals name="encryption_import_room_keys_success">
|
<plurals name="encryption_import_room_keys_success">
|
||||||
<item quantity="one">%1$d/%2$d key imported with success.</item>
|
<item quantity="one">%1$d/%2$d key imported with success.</item>
|
||||||
<item quantity="other">%1$d/%2$d keys imported with success.</item>
|
<item quantity="other">%1$d/%2$d keys imported with success.</item>
|
||||||
|
|
|
@ -61,7 +61,7 @@ interface CryptoService {
|
||||||
|
|
||||||
fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean
|
fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean
|
||||||
|
|
||||||
fun getLiveBlacklistUnverifiedDevices(roomId: String): LiveData<Boolean>
|
fun getLiveBlockUnverifiedDevices(roomId: String): LiveData<Boolean>
|
||||||
|
|
||||||
fun setWarnOnUnknownDevices(warn: Boolean)
|
fun setWarnOnUnknownDevices(warn: Boolean)
|
||||||
|
|
||||||
|
|
|
@ -1177,7 +1177,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
* @return true if the client should encrypt messages only for the verified devices.
|
* @return true if the client should encrypt messages only for the verified devices.
|
||||||
*/
|
*/
|
||||||
override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean {
|
override fun isRoomBlacklistUnverifiedDevices(roomId: String?): Boolean {
|
||||||
return roomId?.let { cryptoStore.getBlacklistUnverifiedDevices(roomId) }
|
return roomId?.let { cryptoStore.getBlockUnverifiedDevices(roomId) }
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,8 +1186,8 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
*
|
*
|
||||||
* @return Live status
|
* @return Live status
|
||||||
*/
|
*/
|
||||||
override fun getLiveBlacklistUnverifiedDevices(roomId: String): LiveData<Boolean> {
|
override fun getLiveBlockUnverifiedDevices(roomId: String): LiveData<Boolean> {
|
||||||
return cryptoStore.getLiveBlacklistUnverifiedDevices(roomId)
|
return cryptoStore.getLiveBlockUnverifiedDevices(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -424,7 +424,7 @@ internal class MXMegolmEncryption(
|
||||||
// an m.new_device.
|
// an m.new_device.
|
||||||
val keys = deviceListManager.downloadKeys(userIds, false)
|
val keys = deviceListManager.downloadKeys(userIds, false)
|
||||||
val encryptToVerifiedDevicesOnly = cryptoStore.getGlobalBlacklistUnverifiedDevices() ||
|
val encryptToVerifiedDevicesOnly = cryptoStore.getGlobalBlacklistUnverifiedDevices() ||
|
||||||
cryptoStore.getBlacklistUnverifiedDevices(roomId)
|
cryptoStore.getBlockUnverifiedDevices(roomId)
|
||||||
|
|
||||||
val devicesInRoom = DeviceInRoomInfo()
|
val devicesInRoom = DeviceInRoomInfo()
|
||||||
val unknownDevices = MXUsersDevicesMap<CryptoDeviceInfo>()
|
val unknownDevices = MXUsersDevicesMap<CryptoDeviceInfo>()
|
||||||
|
|
|
@ -125,14 +125,14 @@ internal interface IMXCryptoStore {
|
||||||
*
|
*
|
||||||
* @return Live status
|
* @return Live status
|
||||||
*/
|
*/
|
||||||
fun getLiveBlacklistUnverifiedDevices(roomId: String): LiveData<Boolean>
|
fun getLiveBlockUnverifiedDevices(roomId: String): LiveData<Boolean>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell if unverified devices should be blacklisted when sending keys.
|
* Tell if unverified devices should be blacklisted when sending keys.
|
||||||
*
|
*
|
||||||
* @return true if should not send keys to unverified devices
|
* @return true if should not send keys to unverified devices
|
||||||
*/
|
*/
|
||||||
fun getBlacklistUnverifiedDevices(roomId: String): Boolean
|
fun getBlockUnverifiedDevices(roomId: String): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define if encryption keys should be sent to unverified devices in this room.
|
* Define if encryption keys should be sent to unverified devices in this room.
|
||||||
|
|
|
@ -1097,7 +1097,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLiveBlacklistUnverifiedDevices(roomId: String): LiveData<Boolean> {
|
override fun getLiveBlockUnverifiedDevices(roomId: String): LiveData<Boolean> {
|
||||||
val liveData = monarchy.findAllMappedWithChanges(
|
val liveData = monarchy.findAllMappedWithChanges(
|
||||||
{ realm: Realm ->
|
{ realm: Realm ->
|
||||||
realm.where<CryptoRoomEntity>()
|
realm.where<CryptoRoomEntity>()
|
||||||
|
@ -1112,7 +1112,7 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBlacklistUnverifiedDevices(roomId: String): Boolean {
|
override fun getBlockUnverifiedDevices(roomId: String): Boolean {
|
||||||
return doWithRealm(realmConfiguration) { realm ->
|
return doWithRealm(realmConfiguration) { realm ->
|
||||||
realm.where<CryptoRoomEntity>()
|
realm.where<CryptoRoomEntity>()
|
||||||
.equalTo(CryptoRoomEntityFields.ROOM_ID, roomId)
|
.equalTo(CryptoRoomEntityFields.ROOM_ID, roomId)
|
||||||
|
|
|
@ -27,4 +27,5 @@ sealed class RoomProfileAction : VectorViewModelAction {
|
||||||
object ShareRoomProfile : RoomProfileAction()
|
object ShareRoomProfile : RoomProfileAction()
|
||||||
object CreateShortcut : RoomProfileAction()
|
object CreateShortcut : RoomProfileAction()
|
||||||
object RestoreEncryptionState : RoomProfileAction()
|
object RestoreEncryptionState : RoomProfileAction()
|
||||||
|
data class SetEncryptToVerifiedDeviceOnly(val enabled: Boolean) : RoomProfileAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import im.vector.app.core.resources.DrawableProvider
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.ui.list.genericFooterItem
|
import im.vector.app.core.ui.list.genericFooterItem
|
||||||
import im.vector.app.core.ui.list.genericPositiveButtonItem
|
import im.vector.app.core.ui.list.genericPositiveButtonItem
|
||||||
|
import im.vector.app.features.form.formSwitchItem
|
||||||
import im.vector.app.features.home.ShortcutCreator
|
import im.vector.app.features.home.ShortcutCreator
|
||||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||||
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
||||||
|
@ -66,6 +67,8 @@ class RoomProfileController @Inject constructor(
|
||||||
fun onUrlInTopicLongClicked(url: String)
|
fun onUrlInTopicLongClicked(url: String)
|
||||||
fun doMigrateToVersion(newVersion: String)
|
fun doMigrateToVersion(newVersion: String)
|
||||||
fun restoreEncryptionState()
|
fun restoreEncryptionState()
|
||||||
|
fun setEncryptedToVerifiedDevicesOnly(enabled: Boolean)
|
||||||
|
fun openGlobalBlockSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildModels(data: RoomProfileViewState?) {
|
override fun buildModels(data: RoomProfileViewState?) {
|
||||||
|
@ -175,6 +178,53 @@ class RoomProfileController @Inject constructor(
|
||||||
}
|
}
|
||||||
buildEncryptionAction(data.actionPermissions, roomSummary)
|
buildEncryptionAction(data.actionPermissions, roomSummary)
|
||||||
|
|
||||||
|
if (roomSummary.isEncrypted && !encryptionMisconfigured) {
|
||||||
|
data.globalCryptoConfig.invoke()?.let { globalConfig ->
|
||||||
|
if (globalConfig.globalBlockUnverifiedDevices) {
|
||||||
|
genericFooterItem {
|
||||||
|
id("globalConfig")
|
||||||
|
centered(false)
|
||||||
|
text(
|
||||||
|
span {
|
||||||
|
+host.stringProvider.getString(R.string.room_settings_global_block_unverified_info_text)
|
||||||
|
apply {
|
||||||
|
if (data.unverifiedDevicesInTheRoom.invoke() == true) {
|
||||||
|
+"\n"
|
||||||
|
+host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.toEpoxyCharSequence()
|
||||||
|
)
|
||||||
|
itemClickAction {
|
||||||
|
host.callback?.openGlobalBlockSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// per room setting is available
|
||||||
|
val shouldBlockUnverified = data.encryptToVerifiedDeviceOnly.invoke()
|
||||||
|
formSwitchItem {
|
||||||
|
id("send_to_unverified")
|
||||||
|
enabled(shouldBlockUnverified != null)
|
||||||
|
title(host.stringProvider.getString(R.string.encryption_never_send_to_unverified_devices_in_room))
|
||||||
|
|
||||||
|
switchChecked(shouldBlockUnverified ?: false)
|
||||||
|
|
||||||
|
apply {
|
||||||
|
if (shouldBlockUnverified == true && data.unverifiedDevicesInTheRoom.invoke() == true) {
|
||||||
|
summary(
|
||||||
|
host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
summary(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listener { value ->
|
||||||
|
host.callback?.setEncryptedToVerifiedDevicesOnly(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// More
|
// More
|
||||||
buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))
|
buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))
|
||||||
buildProfileAction(
|
buildProfileAction(
|
||||||
|
|
|
@ -53,6 +53,7 @@ import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
|
||||||
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
|
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||||
|
import im.vector.app.features.navigation.SettingsActivityPayload
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
@ -346,6 +347,14 @@ class RoomProfileFragment :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setEncryptedToVerifiedDevicesOnly(enabled: Boolean) {
|
||||||
|
roomProfileViewModel.handle(RoomProfileAction.SetEncryptToVerifiedDeviceOnly(enabled))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openGlobalBlockSettings() {
|
||||||
|
navigator.openSettings(requireContext(), SettingsActivityPayload.SecurityPrivacy)
|
||||||
|
}
|
||||||
|
|
||||||
private fun onAvatarClicked(view: View) = withState(roomProfileViewModel) { state ->
|
private fun onAvatarClicked(view: View) = withState(roomProfileViewModel) { state ->
|
||||||
state.roomSummary()?.toMatrixItem()?.let { matrixItem ->
|
state.roomSummary()?.toMatrixItem()?.let { matrixItem ->
|
||||||
navigator.openBigImageViewer(requireActivity(), view, matrixItem)
|
navigator.openBigImageViewer(requireActivity(), view, matrixItem)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package im.vector.app.features.roomprofile
|
package im.vector.app.features.roomprofile
|
||||||
|
|
||||||
|
import androidx.lifecycle.asFlow
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
@ -32,7 +33,11 @@ import im.vector.app.features.home.ShortcutCreator
|
||||||
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
||||||
import im.vector.app.features.session.coroutineScope
|
import im.vector.app.features.session.coroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
|
@ -76,6 +81,45 @@ class RoomProfileViewModel @AssistedInject constructor(
|
||||||
observeBannedRoomMembers(flowRoom)
|
observeBannedRoomMembers(flowRoom)
|
||||||
observePermissions()
|
observePermissions()
|
||||||
observePowerLevels()
|
observePowerLevels()
|
||||||
|
observeCryptoSettings(flowRoom)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeCryptoSettings(flowRoom: FlowRoom) {
|
||||||
|
val perRoomBlockStatus = session.cryptoService().getLiveBlockUnverifiedDevices(initialState.roomId)
|
||||||
|
.asFlow()
|
||||||
|
|
||||||
|
perRoomBlockStatus
|
||||||
|
.execute {
|
||||||
|
copy(encryptToVerifiedDeviceOnly = it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val globalBlockStatus = session.cryptoService().getLiveGlobalCryptoConfig()
|
||||||
|
.asFlow()
|
||||||
|
|
||||||
|
globalBlockStatus
|
||||||
|
.execute {
|
||||||
|
copy(globalCryptoConfig = it)
|
||||||
|
}
|
||||||
|
|
||||||
|
perRoomBlockStatus.combine(globalBlockStatus) { perRoom, global ->
|
||||||
|
perRoom || global.globalBlockUnverifiedDevices
|
||||||
|
}.flatMapLatest {
|
||||||
|
if (it) {
|
||||||
|
flowRoom.liveRoomMembers(roomMemberQueryParams { memberships = Membership.activeMemberships() })
|
||||||
|
.map { it.map { it.userId } }
|
||||||
|
.flatMapLatest {
|
||||||
|
session.cryptoService().getLiveCryptoDeviceInfo(it).asFlow()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flowOf(emptyList())
|
||||||
|
}
|
||||||
|
}.map {
|
||||||
|
it.isNotEmpty()
|
||||||
|
}.execute {
|
||||||
|
copy(
|
||||||
|
unverifiedDevicesInTheRoom = it
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observePowerLevels() {
|
private fun observePowerLevels() {
|
||||||
|
@ -141,6 +185,7 @@ class RoomProfileViewModel @AssistedInject constructor(
|
||||||
is RoomProfileAction.ShareRoomProfile -> handleShareRoomProfile()
|
is RoomProfileAction.ShareRoomProfile -> handleShareRoomProfile()
|
||||||
RoomProfileAction.CreateShortcut -> handleCreateShortcut()
|
RoomProfileAction.CreateShortcut -> handleCreateShortcut()
|
||||||
RoomProfileAction.RestoreEncryptionState -> restoreEncryptionState()
|
RoomProfileAction.RestoreEncryptionState -> restoreEncryptionState()
|
||||||
|
is RoomProfileAction.SetEncryptToVerifiedDeviceOnly -> setEncryptToVerifiedDeviceOnly(action.enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +257,12 @@ class RoomProfileViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setEncryptToVerifiedDeviceOnly(enabled: Boolean) {
|
||||||
|
session.coroutineScope.launch {
|
||||||
|
session.cryptoService().setRoomBlockUnverifiedDevices(room.roomId, enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun restoreEncryptionState() {
|
private fun restoreEncryptionState() {
|
||||||
_viewEvents.post(RoomProfileViewEvents.Loading())
|
_viewEvents.post(RoomProfileViewEvents.Loading())
|
||||||
session.coroutineScope.launch {
|
session.coroutineScope.launch {
|
||||||
|
|
|
@ -20,6 +20,7 @@ package im.vector.app.features.roomprofile
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.MavericksState
|
import com.airbnb.mvrx.MavericksState
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.GlobalCryptoConfig
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||||
|
@ -36,6 +37,9 @@ data class RoomProfileViewState(
|
||||||
val canUpgradeRoom: Boolean = false,
|
val canUpgradeRoom: Boolean = false,
|
||||||
val isTombstoned: Boolean = false,
|
val isTombstoned: Boolean = false,
|
||||||
val canUpdateRoomState: Boolean = false,
|
val canUpdateRoomState: Boolean = false,
|
||||||
|
val encryptToVerifiedDeviceOnly: Async<Boolean> = Uninitialized,
|
||||||
|
val globalCryptoConfig: Async<GlobalCryptoConfig> = Uninitialized,
|
||||||
|
val unverifiedDevicesInTheRoom: Async<Boolean> = Uninitialized,
|
||||||
) : MavericksState {
|
) : MavericksState {
|
||||||
|
|
||||||
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
||||||
|
|
|
@ -28,7 +28,6 @@ sealed class RoomSettingsAction : VectorViewModelAction {
|
||||||
data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction()
|
data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction()
|
||||||
data class SetRoomJoinRule(val roomJoinRule: RoomJoinRules) : RoomSettingsAction()
|
data class SetRoomJoinRule(val roomJoinRule: RoomJoinRules) : RoomSettingsAction()
|
||||||
data class SetRoomGuestAccess(val guestAccess: GuestAccess) : RoomSettingsAction()
|
data class SetRoomGuestAccess(val guestAccess: GuestAccess) : RoomSettingsAction()
|
||||||
data class SetEncryptToVerifiedDeviceOnly(val enabled: Boolean) : RoomSettingsAction()
|
|
||||||
|
|
||||||
object Save : RoomSettingsAction()
|
object Save : RoomSettingsAction()
|
||||||
object Cancel : RoomSettingsAction()
|
object Cancel : RoomSettingsAction()
|
||||||
|
|
|
@ -22,7 +22,6 @@ import im.vector.app.core.epoxy.dividerItem
|
||||||
import im.vector.app.core.epoxy.profiles.buildProfileAction
|
import im.vector.app.core.epoxy.profiles.buildProfileAction
|
||||||
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.ui.list.genericFooterItem
|
|
||||||
import im.vector.app.core.ui.list.verticalMarginItem
|
import im.vector.app.core.ui.list.verticalMarginItem
|
||||||
import im.vector.app.core.utils.DimensionConverter
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
import im.vector.app.features.form.formEditTextItem
|
import im.vector.app.features.form.formEditTextItem
|
||||||
|
@ -31,8 +30,6 @@ import im.vector.app.features.form.formSwitchItem
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter
|
import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibilityFormatter
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
|
|
||||||
import me.gujun.android.span.span
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
@ -55,8 +52,6 @@ class RoomSettingsController @Inject constructor(
|
||||||
fun onHistoryVisibilityClicked()
|
fun onHistoryVisibilityClicked()
|
||||||
fun onJoinRuleClicked()
|
fun onJoinRuleClicked()
|
||||||
fun onToggleGuestAccess()
|
fun onToggleGuestAccess()
|
||||||
fun setEncryptedToVerifiedDevicesOnly(enabled: Boolean)
|
|
||||||
fun openGlobalBlockSettings()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var callback: Callback? = null
|
var callback: Callback? = null
|
||||||
|
@ -150,54 +145,54 @@ class RoomSettingsController @Inject constructor(
|
||||||
id("guestAccessDivider")
|
id("guestAccessDivider")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// // Security
|
||||||
|
// buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
|
||||||
|
|
||||||
// Security
|
// data.globalCryptoConfig.invoke()?.let { globalConfig ->
|
||||||
buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
|
// if (globalConfig.globalBlockUnverifiedDevices) {
|
||||||
|
// genericFooterItem {
|
||||||
data.globalCryptoConfig.invoke()?.let { globalConfig ->
|
// id("globalConfig")
|
||||||
if (globalConfig.globalBlockUnverifiedDevices) {
|
// centered(false)
|
||||||
genericFooterItem {
|
// text(
|
||||||
id("globalConfig")
|
// span {
|
||||||
centered(false)
|
// +host.stringProvider.getString(R.string.room_settings_global_block_unverified_info_text)
|
||||||
text(
|
// apply {
|
||||||
span {
|
// if (data.unverifiedDevicesInTheRoom.invoke() == true) {
|
||||||
+host.stringProvider.getString(R.string.room_settings_global_blacklist_unverified_info_text)
|
// +"\n"
|
||||||
apply {
|
// +host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
||||||
if (data.unverifiedDevicesInTheRoom.invoke() == true) {
|
// }
|
||||||
+"\n"
|
// }
|
||||||
+host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
// }.toEpoxyCharSequence()
|
||||||
}
|
// )
|
||||||
}
|
// itemClickAction {
|
||||||
}.toEpoxyCharSequence()
|
// host.callback?.openGlobalBlockSettings()
|
||||||
)
|
// }
|
||||||
itemClickAction {
|
// }
|
||||||
host.callback?.openGlobalBlockSettings()
|
// } else {
|
||||||
}
|
// // per room setting is available
|
||||||
}
|
// val shouldBlockUnverified = data.encryptToVerifiedDeviceOnly.invoke()
|
||||||
} else {
|
// formSwitchItem {
|
||||||
// per room setting is available
|
// id("send_to_unverified")
|
||||||
val shouldBlockUnverified = data.encryptToVerifiedDeviceOnly.invoke()
|
// enabled(shouldBlockUnverified != null)
|
||||||
formSwitchItem {
|
// title(host.stringProvider.getString(R.string.encryption_never_send_to_unverified_devices_in_room))
|
||||||
id("send_to_unverified")
|
//
|
||||||
enabled(shouldBlockUnverified != null)
|
// switchChecked(shouldBlockUnverified ?: false)
|
||||||
title(host.stringProvider.getString(R.string.encryption_never_send_to_unverified_devices_in_room))
|
//
|
||||||
|
// apply {
|
||||||
switchChecked(shouldBlockUnverified ?: false)
|
// if (shouldBlockUnverified == true && data.unverifiedDevicesInTheRoom.invoke() == true) {
|
||||||
|
// summary(
|
||||||
apply {
|
// host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
||||||
if (shouldBlockUnverified == true && data.unverifiedDevicesInTheRoom.invoke() == true) {
|
// )
|
||||||
summary(
|
// } else {
|
||||||
host.stringProvider.getString(R.string.some_devices_will_not_be_able_to_decrypt)
|
// summary(null)
|
||||||
)
|
// }
|
||||||
} else {
|
// }
|
||||||
summary(null)
|
// listener { value ->
|
||||||
}
|
// host.callback?.setEncryptedToVerifiedDevicesOnly(value)
|
||||||
}
|
// }
|
||||||
listener { value ->
|
// }
|
||||||
host.callback?.setEncryptedToVerifiedDevicesOnly(value)
|
// }
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ import im.vector.app.core.utils.toast
|
||||||
import im.vector.app.databinding.FragmentRoomSettingGenericBinding
|
import im.vector.app.databinding.FragmentRoomSettingGenericBinding
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.navigation.SettingsActivityPayload
|
|
||||||
import im.vector.app.features.roomprofile.RoomProfileArgs
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
import im.vector.app.features.roomprofile.RoomProfileSharedActionViewModel
|
||||||
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
|
import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
|
||||||
|
@ -200,14 +199,6 @@ class RoomSettingsFragment :
|
||||||
viewModel.handle(RoomSettingsAction.SetRoomGuestAccess(toggled))
|
viewModel.handle(RoomSettingsAction.SetRoomGuestAccess(toggled))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setEncryptedToVerifiedDevicesOnly(enabled: Boolean) {
|
|
||||||
viewModel.handle(RoomSettingsAction.SetEncryptToVerifiedDeviceOnly(enabled))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openGlobalBlockSettings() {
|
|
||||||
navigator.openSettings(requireContext(), SettingsActivityPayload.SecurityPrivacy)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onImageReady(uri: Uri?) {
|
override fun onImageReady(uri: Uri?) {
|
||||||
uri ?: return
|
uri ?: return
|
||||||
viewModel.handle(
|
viewModel.handle(
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package im.vector.app.features.roomprofile.settings
|
package im.vector.app.features.roomprofile.settings
|
||||||
|
|
||||||
import androidx.core.net.toFile
|
import androidx.core.net.toFile
|
||||||
import androidx.lifecycle.asFlow
|
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
@ -26,12 +25,8 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
|
||||||
import im.vector.app.features.session.coroutineScope
|
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -42,8 +37,6 @@ 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.getRoom
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||||
|
@ -90,39 +83,6 @@ class RoomSettingsViewModel @AssistedInject constructor(
|
||||||
canUpgradeToRestricted = couldUpgradeToRestricted
|
canUpgradeToRestricted = couldUpgradeToRestricted
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
session.cryptoService().getLiveBlacklistUnverifiedDevices(initialState.roomId)
|
|
||||||
.asFlow()
|
|
||||||
.execute {
|
|
||||||
copy(encryptToVerifiedDeviceOnly = it)
|
|
||||||
}
|
|
||||||
|
|
||||||
session.cryptoService().getLiveGlobalCryptoConfig()
|
|
||||||
.asFlow()
|
|
||||||
.execute {
|
|
||||||
copy(globalCryptoConfig = it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val flowRoom = room.flow()
|
|
||||||
session.cryptoService().getLiveBlacklistUnverifiedDevices(initialState.roomId)
|
|
||||||
.asFlow()
|
|
||||||
.flatMapLatest {
|
|
||||||
if (it) {
|
|
||||||
flowRoom.liveRoomMembers(roomMemberQueryParams { memberships = Membership.activeMemberships() })
|
|
||||||
.map { it.map { it.userId } }
|
|
||||||
.flatMapLatest {
|
|
||||||
session.cryptoService().getLiveCryptoDeviceInfo(it).asFlow()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
flowOf(emptyList())
|
|
||||||
}
|
|
||||||
}.map {
|
|
||||||
it.isNotEmpty()
|
|
||||||
}.execute {
|
|
||||||
copy(
|
|
||||||
unverifiedDevicesInTheRoom = it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeState() {
|
private fun observeState() {
|
||||||
|
@ -252,7 +212,6 @@ class RoomSettingsViewModel @AssistedInject constructor(
|
||||||
is RoomSettingsAction.SetRoomGuestAccess -> handleSetGuestAccess(action)
|
is RoomSettingsAction.SetRoomGuestAccess -> handleSetGuestAccess(action)
|
||||||
is RoomSettingsAction.Save -> saveSettings()
|
is RoomSettingsAction.Save -> saveSettings()
|
||||||
is RoomSettingsAction.Cancel -> cancel()
|
is RoomSettingsAction.Cancel -> cancel()
|
||||||
is RoomSettingsAction.SetEncryptToVerifiedDeviceOnly -> setEncryptToVerifiedDeviceOnly(action.enabled)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,12 +233,6 @@ class RoomSettingsViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setEncryptToVerifiedDeviceOnly(enabled: Boolean) {
|
|
||||||
session.coroutineScope.launch {
|
|
||||||
session.cryptoService().setRoomBlockUnverifiedDevices(room.roomId, enabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleSetAvatarAction(action: RoomSettingsAction.SetAvatarAction) {
|
private fun handleSetAvatarAction(action: RoomSettingsAction.SetAvatarAction) {
|
||||||
setState {
|
setState {
|
||||||
deletePendingAvatar(this)
|
deletePendingAvatar(this)
|
||||||
|
|
|
@ -23,7 +23,6 @@ import com.airbnb.mvrx.Uninitialized
|
||||||
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.features.roomprofile.RoomProfileArgs
|
import im.vector.app.features.roomprofile.RoomProfileArgs
|
||||||
import org.matrix.android.sdk.api.session.crypto.GlobalCryptoConfig
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
|
@ -47,9 +46,6 @@ data class RoomSettingsViewState(
|
||||||
val actionPermissions: ActionPermissions = ActionPermissions(),
|
val actionPermissions: ActionPermissions = ActionPermissions(),
|
||||||
val supportsRestricted: Boolean = false,
|
val supportsRestricted: Boolean = false,
|
||||||
val canUpgradeToRestricted: Boolean = false,
|
val canUpgradeToRestricted: Boolean = false,
|
||||||
val encryptToVerifiedDeviceOnly: Async<Boolean> = Uninitialized,
|
|
||||||
val globalCryptoConfig: Async<GlobalCryptoConfig> = Uninitialized,
|
|
||||||
val unverifiedDevicesInTheRoom: Async<Boolean> = Uninitialized,
|
|
||||||
) : MavericksState {
|
) : MavericksState {
|
||||||
|
|
||||||
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
|
||||||
|
|
Loading…
Reference in New Issue