From f5790e5dc277a8bb873ba23fedd3e1227c1f2a1c Mon Sep 17 00:00:00 2001 From: onurays Date: Mon, 22 Jun 2020 10:29:34 +0300 Subject: [PATCH] Implementation of room history readability. --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 4 ++ .../api/session/room/state/StateService.kt | 5 +++ .../session/room/state/DefaultStateService.kt | 9 +++++ .../settings/RoomSettingsAction.kt | 2 + .../settings/RoomSettingsController.kt | 7 +++- .../settings/RoomSettingsFragment.kt | 40 +++++++++++++++++-- .../settings/RoomSettingsViewModel.kt | 22 +++++++--- .../settings/RoomSettingsViewState.kt | 2 + 8 files changed, 81 insertions(+), 10 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index a6c135c13f..876f01de02 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -111,6 +111,10 @@ class RxRoom(private val room: Room) { room.updateName(name, it) } + fun updateHistoryReadability(readability: String) = completableBuilder { + room.updateHistoryReadability(readability, it) + } + fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder { room.updateAvatar(avatarUri, fileName, it) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt index 64066640b4..9bfaff00ca 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/state/StateService.kt @@ -37,6 +37,11 @@ interface StateService { */ fun updateName(name: String, callback: MatrixCallback): Cancelable + /** + * Update the history readability of the room + */ + fun updateHistoryReadability(readability: String, callback: MatrixCallback): Cancelable + /** * Update the avatar of the room */ diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt index ebfc3398b2..77fcd9a9bb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/state/DefaultStateService.kt @@ -111,6 +111,15 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private ) } + override fun updateHistoryReadability(readability: String, callback: MatrixCallback): Cancelable { + return sendStateEvent( + eventType = EventType.STATE_ROOM_HISTORY_VISIBILITY, + body = mapOf("history_visibility" to readability), + callback = callback, + stateKey = null + ) + } + override fun updateAvatar(avatarUri: Uri, fileName: String, callback: MatrixCallback): Cancelable { val cancelableBag = CancelableBag() val workerParams = UploadAvatarWorker.Params(sessionId, avatarUri, fileName) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt index f740c22d6d..aadb6584a5 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsAction.kt @@ -16,6 +16,7 @@ package im.vector.riotx.features.roomprofile.settings +import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility import im.vector.riotx.core.platform.VectorViewModelAction import im.vector.riotx.multipicker.entity.MultiPickerImageType @@ -23,6 +24,7 @@ sealed class RoomSettingsAction : VectorViewModelAction { data class SetRoomName(val newName: String) : RoomSettingsAction() data class SetRoomTopic(val newTopic: String) : RoomSettingsAction() data class SetRoomAvatar(val image: MultiPickerImageType) : RoomSettingsAction() + data class SetRoomHistoryVisibility(val visibility: RoomHistoryVisibility) : RoomSettingsAction() object EnableEncryption : RoomSettingsAction() object Save : RoomSettingsAction() } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt index 41fff7e988..f29c6cc65e 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsController.kt @@ -58,6 +58,7 @@ class RoomSettingsController @Inject constructor( val roomSummary = data?.roomSummary?.invoke() ?: return val historyVisibility = data.historyVisibilityEvent?.let { formatRoomHistoryVisibilityEvent(it) } ?: "" + val newHistoryVisibility = data.newHistoryVisibility?.let { formatRoomHistoryVisibility(it) } buildProfileSection( stringProvider.getString(R.string.settings) @@ -88,7 +89,7 @@ class RoomSettingsController @Inject constructor( buildProfileAction( id = "historyReadability", title = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_title), - subtitle = historyVisibility.toString(), + subtitle = newHistoryVisibility ?: historyVisibility, dividerColor = dividerColor, divider = false, editable = true, @@ -131,6 +132,10 @@ class RoomSettingsController @Inject constructor( private fun formatRoomHistoryVisibilityEvent(event: Event): String? { val historyVisibility = event.getClearContent().toModel()?.historyVisibility ?: return null + return formatRoomHistoryVisibility(historyVisibility) + } + + private fun formatRoomHistoryVisibility(historyVisibility: RoomHistoryVisibility): String { val formattedVisibility = when (historyVisibility) { RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared) RoomHistoryVisibility.INVITED -> stringProvider.getString(R.string.notice_room_visibility_invited) diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt index c75a4bda71..8e25646637 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsFragment.kt @@ -27,12 +27,16 @@ import androidx.core.view.isVisible import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import im.vector.matrix.android.api.session.events.model.toModel +import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility +import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.toast import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.roomprofile.RoomProfileArgs @@ -45,7 +49,8 @@ import javax.inject.Inject class RoomSettingsFragment @Inject constructor( val viewModelFactory: RoomSettingsViewModel.Factory, private val controller: RoomSettingsController, - private val avatarRenderer: AvatarRenderer + private val avatarRenderer: AvatarRenderer, + private val stringProvider: StringProvider ) : VectorBaseFragment(), RoomSettingsController.Callback { private val viewModel: RoomSettingsViewModel by fragmentViewModel() @@ -153,7 +158,36 @@ class RoomSettingsFragment @Inject constructor( super.onActivityResult(requestCode, resultCode, data) } - override fun onHistoryVisibilityClicked() { - + override fun onHistoryVisibilityClicked() = withState(viewModel) { state -> + val historyVisibilities = arrayOf( + RoomHistoryVisibility.SHARED, + RoomHistoryVisibility.INVITED, + RoomHistoryVisibility.JOINED, + RoomHistoryVisibility.WORLD_READABLE + ) + val currentHistoryVisibility = + state.newHistoryVisibility ?: state.historyVisibilityEvent?.getClearContent().toModel()?.historyVisibility + val currentHistoryVisibilityIndex = historyVisibilities.indexOf(currentHistoryVisibility) + + AlertDialog.Builder(requireContext()).apply { + setTitle(R.string.room_settings_room_read_history_rules_pref_title) + setSingleChoiceItems(historyVisibilities.map { formatHistoryVisibility(it) }.toTypedArray(), currentHistoryVisibilityIndex) { dialog, which -> + if (which != currentHistoryVisibilityIndex) { + viewModel.handle(RoomSettingsAction.SetRoomHistoryVisibility(historyVisibilities[which])) + } + dialog.cancel() + } + show() + } + return@withState + } + + private fun formatHistoryVisibility(historyVisibility: RoomHistoryVisibility): String { + return when (historyVisibility) { + RoomHistoryVisibility.SHARED -> stringProvider.getString(R.string.notice_room_visibility_shared) + RoomHistoryVisibility.INVITED -> stringProvider.getString(R.string.notice_room_visibility_invited) + RoomHistoryVisibility.JOINED -> stringProvider.getString(R.string.notice_room_visibility_joined) + RoomHistoryVisibility.WORLD_READABLE -> stringProvider.getString(R.string.notice_room_visibility_world_readable) + } } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt index db46b6f9d7..26da0bb478 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewModel.kt @@ -29,6 +29,7 @@ import im.vector.matrix.rx.unwrap import im.vector.riotx.core.platform.VectorViewModel import io.reactivex.Completable import io.reactivex.Observable +import java.util.Locale import java.util.UUID class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: RoomSettingsViewState, @@ -71,20 +72,24 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: override fun handle(action: RoomSettingsAction) { when (action) { - is RoomSettingsAction.EnableEncryption -> handleEnableEncryption() - is RoomSettingsAction.SetRoomName -> { + is RoomSettingsAction.EnableEncryption -> handleEnableEncryption() + is RoomSettingsAction.SetRoomName -> { setState { copy(newName = action.newName) } setState { copy(showSaveAction = shouldShowSaveAction(this)) } } - is RoomSettingsAction.SetRoomTopic -> { + is RoomSettingsAction.SetRoomTopic -> { setState { copy(newTopic = action.newTopic) } setState { copy(showSaveAction = shouldShowSaveAction(this)) } } - is RoomSettingsAction.SetRoomAvatar -> { + is RoomSettingsAction.SetRoomAvatar -> { setState { copy(newAvatar = action.image) } setState { copy(showSaveAction = shouldShowSaveAction(this)) } } - is RoomSettingsAction.Save -> saveSettings() + is RoomSettingsAction.SetRoomHistoryVisibility -> { + setState { copy(newHistoryVisibility = action.visibility) } + setState { copy(showSaveAction = shouldShowSaveAction(this)) } + } + is RoomSettingsAction.Save -> saveSettings() } } @@ -92,6 +97,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: val summary = state.roomSummary.invoke() return summary?.displayName != state.newName || summary?.topic != state.newTopic || + state.newHistoryVisibility != null || state.newAvatar != null } @@ -109,6 +115,10 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: operationList.add(room.rx().updateTopic(state.newTopic ?: "")) } + if (state.newHistoryVisibility != null) { + operationList.add(room.rx().updateHistoryReadability(state.newHistoryVisibility.name.toLowerCase(Locale.ROOT))) + } + if (state.newAvatar != null) { operationList.add(room.rx().updateAvatar(state.newAvatar.contentUri, state.newAvatar.displayName ?: UUID.randomUUID().toString())) } @@ -119,7 +129,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState: .subscribe( { postLoading(false) - setState { copy(newAvatar = null) } + setState { copy(newAvatar = null, newHistoryVisibility = null) } setState { copy(showSaveAction = shouldShowSaveAction(this)) } _viewEvents.post(RoomSettingsViewEvents.Success) }, diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt index 3a953f2d18..e456f753c7 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/settings/RoomSettingsViewState.kt @@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.riotx.features.roomprofile.RoomProfileArgs import im.vector.riotx.multipicker.entity.MultiPickerImageType @@ -32,6 +33,7 @@ data class RoomSettingsViewState( val newName: String? = null, val newTopic: String? = null, val newAvatar: MultiPickerImageType? = null, + val newHistoryVisibility: RoomHistoryVisibility? = null, val showSaveAction: Boolean = false ) : MvRxState {