Merge pull request #2407 from vector-im/feature/bma/move_enable_encryption

Move "Enable Encryption" from room setting screen to room profile screen
This commit is contained in:
Benoit Marty 2020-11-19 15:17:13 +01:00 committed by GitHub
commit 465b33b006
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 99 additions and 63 deletions

View file

@ -9,6 +9,7 @@ Improvements 🙌:
- Open an existing DM instead of creating a new one (#2319)
- Ask for explicit user consent to send their contact details to the identity server (#2375)
- Handle events of type "m.room.server_acl" (#890)
- Move "Enable Encryption" from room setting screen to room profile screen (#2394)
Bugfix 🐛:
- Fix issue when restoring draft after sharing (#2287)

View file

@ -21,6 +21,7 @@ import im.vector.app.core.platform.VectorViewModelAction
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
sealed class RoomProfileAction : VectorViewModelAction {
object EnableEncryption : RoomProfileAction()
object LeaveRoom : RoomProfileAction()
data class ChangeRoomNotificationState(val notificationState: RoomNotificationState) : RoomProfileAction()
object ShareRoomProfile : RoomProfileAction()

View file

@ -28,6 +28,7 @@ import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.features.home.ShortcutCreator
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import javax.inject.Inject
class RoomProfileController @Inject constructor(
@ -43,6 +44,7 @@ class RoomProfileController @Inject constructor(
interface Callback {
fun onLearnMoreClicked()
fun onEnableEncryptionClicked()
fun onMemberListClicked()
fun onBannedMemberListClicked()
fun onNotificationsClicked()
@ -84,6 +86,7 @@ class RoomProfileController @Inject constructor(
centered(false)
text(stringProvider.getString(learnMoreSubtitle))
}
buildEncryptionAction(data.actionPermissions, roomSummary)
// More
buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))
@ -171,4 +174,29 @@ class RoomProfileController @Inject constructor(
)
}
}
private fun buildEncryptionAction(actionPermissions: RoomProfileViewState.ActionPermissions, roomSummary: RoomSummary) {
if (!roomSummary.isEncrypted) {
if (actionPermissions.canEnableEncryption) {
buildProfileAction(
id = "enableEncryption",
title = stringProvider.getString(R.string.room_settings_enable_encryption),
dividerColor = dividerColor,
icon = R.drawable.ic_shield_black,
divider = false,
editable = false,
action = { callback?.onEnableEncryptionClicked() }
)
} else {
buildProfileAction(
id = "enableEncryption",
title = stringProvider.getString(R.string.room_settings_enable_encryption_no_permission),
dividerColor = dividerColor,
icon = R.drawable.ic_shield_black,
divider = false,
editable = false
)
}
}
}
}

View file

@ -49,6 +49,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
import im.vector.app.features.media.BigImageViewerActivity
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_matrix_profile.*
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
import kotlinx.android.synthetic.main.view_stub_room_profile_header.*
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
import org.matrix.android.sdk.api.util.MatrixItem
@ -87,6 +88,7 @@ class RoomProfileFragment @Inject constructor(
it.layoutResource = R.layout.view_stub_room_profile_header
it.inflate()
}
setupWaitingView()
setupToolbar(matrixProfileToolbar)
setupRecyclerView()
appBarStateChangeListener = MatrixItemAppBarStateChangeListener(
@ -111,6 +113,11 @@ class RoomProfileFragment @Inject constructor(
setupLongClicks()
}
private fun setupWaitingView() {
waiting_view_status_text.setText(R.string.please_wait)
waiting_view_status_text.isVisible = true
}
private fun setupLongClicks() {
roomProfileNameView.copyOnLongClick()
roomProfileAliasView.copyOnLongClick()
@ -155,6 +162,8 @@ class RoomProfileFragment @Inject constructor(
}
override fun invalidate() = withState(roomProfileViewModel) { state ->
waiting_view.isVisible = state.isLoading
state.roomSummary()?.also {
if (it.membership.isLeft()) {
Timber.w("The room has been left")
@ -187,6 +196,17 @@ class RoomProfileFragment @Inject constructor(
vectorBaseActivity.notImplemented()
}
override fun onEnableEncryptionClicked() {
AlertDialog.Builder(requireActivity())
.setTitle(R.string.room_settings_enable_encryption_dialog_title)
.setMessage(R.string.room_settings_enable_encryption_dialog_content)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.room_settings_enable_encryption_dialog_submit) { _, _ ->
roomProfileViewModel.handle(RoomProfileAction.EnableEncryption)
}
.show()
}
override fun onMemberListClicked() {
roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomMembers)
}

View file

@ -28,12 +28,15 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.ShortcutCreator
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
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.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.rx.RxRoom
import org.matrix.android.sdk.rx.rx
import org.matrix.android.sdk.rx.unwrap
@ -65,6 +68,7 @@ class RoomProfileViewModel @AssistedInject constructor(
val rxRoom = room.rx()
observeRoomSummary(rxRoom)
observeBannedRoomMembers(rxRoom)
observePermissions()
}
private fun observeRoomSummary(rxRoom: RxRoom) {
@ -82,8 +86,22 @@ class RoomProfileViewModel @AssistedInject constructor(
}
}
private fun observePermissions() {
PowerLevelsObservableFactory(room)
.createObservable()
.subscribe {
val powerLevelsHelper = PowerLevelsHelper(it)
val permissions = RoomProfileViewState.ActionPermissions(
canEnableEncryption = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
)
setState { copy(actionPermissions = permissions) }
}
.disposeOnClear()
}
override fun handle(action: RoomProfileAction) {
when (action) {
is RoomProfileAction.EnableEncryption -> handleEnableEncryption()
RoomProfileAction.LeaveRoom -> handleLeaveRoom()
is RoomProfileAction.ChangeRoomNotificationState -> handleChangeNotificationMode(action)
is RoomProfileAction.ShareRoomProfile -> handleShareRoomProfile()
@ -91,6 +109,24 @@ class RoomProfileViewModel @AssistedInject constructor(
}.exhaustive
}
private fun handleEnableEncryption() {
postLoading(true)
viewModelScope.launch {
val result = runCatching { room.enableEncryption() }
postLoading(false)
result.onFailure { failure ->
_viewEvents.post(RoomProfileViewEvents.Failure(failure))
}
}
}
private fun postLoading(isLoading: Boolean) {
setState {
copy(isLoading = isLoading)
}
}
private fun handleCreateShortcut() {
viewModelScope.launch(Dispatchers.IO) {
withState { state ->

View file

@ -26,8 +26,14 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
data class RoomProfileViewState(
val roomId: String,
val roomSummary: Async<RoomSummary> = Uninitialized,
val bannedMembership: Async<List<RoomMemberSummary>> = Uninitialized
val bannedMembership: Async<List<RoomMemberSummary>> = Uninitialized,
val actionPermissions: ActionPermissions = ActionPermissions(),
val isLoading: Boolean = false
) : MvRxState {
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
data class ActionPermissions(
val canEnableEncryption: Boolean = false
)
}

View file

@ -25,7 +25,6 @@ sealed class RoomSettingsAction : VectorViewModelAction {
data class SetRoomTopic(val newTopic: String) : RoomSettingsAction()
data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction()
data class SetRoomCanonicalAlias(val newCanonicalAlias: String) : RoomSettingsAction()
object EnableEncryption : RoomSettingsAction()
object Save : RoomSettingsAction()
object Cancel : RoomSettingsAction()
}

View file

@ -29,7 +29,6 @@ import im.vector.app.features.home.room.detail.timeline.format.RoomHistoryVisibi
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.RoomHistoryVisibilityContent
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
@ -44,7 +43,6 @@ class RoomSettingsController @Inject constructor(
// Delete the avatar, or cancel an avatar change
fun onAvatarDelete()
fun onAvatarChange()
fun onEnableEncryptionClicked()
fun onNameChanged(name: String)
fun onTopicChanged(topic: String)
fun onHistoryVisibilityClicked()
@ -130,33 +128,6 @@ class RoomSettingsController @Inject constructor(
editable = data.actionPermissions.canChangeHistoryReadability,
action = { if (data.actionPermissions.canChangeHistoryReadability) callback?.onHistoryVisibilityClicked() }
)
buildEncryptionAction(data.actionPermissions, roomSummary)
}
private fun buildEncryptionAction(actionPermissions: RoomSettingsViewState.ActionPermissions, roomSummary: RoomSummary) {
if (!actionPermissions.canEnableEncryption) {
return
}
if (roomSummary.isEncrypted) {
buildProfileAction(
id = "encryption",
title = stringProvider.getString(R.string.room_settings_addresses_e2e_enabled),
dividerColor = dividerColor,
divider = false,
editable = false
)
} else {
buildProfileAction(
id = "encryption",
title = stringProvider.getString(R.string.room_settings_enable_encryption),
subtitle = stringProvider.getString(R.string.room_settings_enable_encryption_warning),
dividerColor = dividerColor,
divider = false,
editable = true,
action = { callback?.onEnableEncryptionClicked() }
)
}
}
private fun formatRoomHistoryVisibilityEvent(event: Event): String? {

View file

@ -127,17 +127,6 @@ class RoomSettingsFragment @Inject constructor(
invalidateOptionsMenu()
}
override fun onEnableEncryptionClicked() {
AlertDialog.Builder(requireActivity())
.setTitle(R.string.room_settings_enable_encryption_dialog_title)
.setMessage(R.string.room_settings_enable_encryption_dialog_content)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.room_settings_enable_encryption_dialog_submit) { _, _ ->
viewModel.handle(RoomSettingsAction.EnableEncryption)
}
.show()
}
override fun onNameChanged(name: String) {
viewModel.handle(RoomSettingsAction.SetRoomName(name))
}

View file

@ -17,7 +17,6 @@
package im.vector.app.features.roomprofile.settings
import androidx.core.net.toFile
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
@ -28,7 +27,6 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import io.reactivex.Completable
import io.reactivex.Observable
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
@ -118,8 +116,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
canChangeCanonicalAlias = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true,
EventType.STATE_ROOM_CANONICAL_ALIAS),
canChangeHistoryReadability = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true,
EventType.STATE_ROOM_HISTORY_VISIBILITY),
canEnableEncryption = powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, EventType.STATE_ROOM_ENCRYPTION)
EventType.STATE_ROOM_HISTORY_VISIBILITY)
)
setState { copy(actionPermissions = permissions) }
}
@ -142,7 +139,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
override fun handle(action: RoomSettingsAction) {
when (action) {
is RoomSettingsAction.EnableEncryption -> handleEnableEncryption()
is RoomSettingsAction.SetAvatarAction -> handleSetAvatarAction(action)
is RoomSettingsAction.SetRoomName -> setState { copy(newName = action.newName) }
is RoomSettingsAction.SetRoomTopic -> setState { copy(newTopic = action.newTopic) }
@ -226,18 +222,6 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
)
}
private fun handleEnableEncryption() {
postLoading(true)
viewModelScope.launch {
val result = runCatching { room.enableEncryption() }
postLoading(false)
result.onFailure { failure ->
_viewEvents.post(RoomSettingsViewEvents.Failure(failure))
}
}
}
private fun postLoading(isLoading: Boolean) {
setState {
copy(isLoading = isLoading)

View file

@ -47,8 +47,7 @@ data class RoomSettingsViewState(
val canChangeName: Boolean = false,
val canChangeTopic: Boolean = false,
val canChangeCanonicalAlias: Boolean = false,
val canChangeHistoryReadability: Boolean = false,
val canEnableEncryption: Boolean = false
val canChangeHistoryReadability: Boolean = false
)
sealed class AvatarAction {

View file

@ -95,7 +95,6 @@
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
@ -105,4 +104,6 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/item_profile_action" />
<include layout="@layout/merge_overlay_waiting_view" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -2200,7 +2200,8 @@
<!-- Title for category in the settings which affect the behavior of the message editor (ex: enable Markdown, send typing notification, etc.) -->
<string name="settings_category_composer">Message editor</string>
<string name="room_settings_enable_encryption">Enable end-to-end encryption</string>
<string name="room_settings_enable_encryption">Enable end-to-end encryption…</string>
<string name="room_settings_enable_encryption_no_permission">You don\'t have permission to enable encryption in this room.</string>
<string name="room_settings_enable_encryption_warning">Once enabled, encryption cannot be disabled.</string>
<string name="room_settings_enable_encryption_dialog_title">Enable encryption?</string>