diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileAction.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileAction.kt index 7a171ca3e5..1467889b4a 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileAction.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileAction.kt @@ -28,4 +28,5 @@ sealed class RoomMemberProfileAction : VectorViewModelAction { object VerifyUser : RoomMemberProfileAction() object ShareRoomMemberProfile : RoomMemberProfileAction() data class SetPowerLevel(val previousValue: Int, val newValue: Int, val askForValidation: Boolean) : RoomMemberProfileAction() + data class SetUserColorOverride(val newColor: String) : RoomMemberProfileAction() } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt index 2aa3a08b53..06ba18f4a7 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileController.kt @@ -178,6 +178,7 @@ class RoomMemberProfileController @Inject constructor( id = "overrideColor", editable = false, title = stringProvider.getString(R.string.room_member_override_nick_color), + subtitle = state.userColorOverride, divider = false, action = { callback?.onOverrideColorClicked() } ) diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index 3d97ce10dd..2bd93e41da 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -24,7 +24,6 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible -import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success @@ -56,10 +55,8 @@ import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs -import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel -import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.util.MatrixItem import javax.inject.Inject @@ -328,36 +325,20 @@ class RoomMemberProfileFragment @Inject constructor( navigator.openBigImageViewer(requireActivity(), view, userMatrixItem) } - override fun onOverrideColorClicked(): Unit = withState(viewModel) { state -> + override fun onOverrideColorClicked(): Unit = withState(viewModel) { state -> val inflater = requireActivity().layoutInflater val layout = inflater.inflate(R.layout.dialog_base_edit_text, null) val views = DialogBaseEditTextBinding.bind(layout) - val session = injector().activeSessionHolder().getActiveSession() - val overrideColorsSetting = session.accountDataService().getUserAccountDataEvent(UserAccountDataTypes.TYPE_OVERRIDE_COLORS) - val overrideColorSpecs = overrideColorsSetting?.content?.toMap().orEmpty() - val userId = state.userId - val overrideColorSpec : String? = overrideColorSpecs[userId]?.toString() - views.editText.setText(overrideColorSpec) + views.editText.setText(state.userColorOverride) views.editText.hint = "#000000" MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.room_member_override_nick_color) .setView(layout) .setPositiveButton(R.string.ok) { _, _ -> - val newOverrideColorSpec = views.editText.text.toString() - if (newOverrideColorSpec != overrideColorSpec) { - val newOverrideColorSpecs = overrideColorSpecs.toMutableMap() - if (matrixItemColorProvider.setOverrideColor(userId, newOverrideColorSpec)) { - newOverrideColorSpecs[userId] = newOverrideColorSpec - } else { - newOverrideColorSpecs.remove(userId) - } - viewModel.viewModelScope.launch { - session.accountDataService().updateUserAccountData( - type = UserAccountDataTypes.TYPE_OVERRIDE_COLORS, - content = newOverrideColorSpecs) - } - invalidate() + val newColor = views.editText.text.toString() + if (newColor != state.userColorOverride) { + viewModel.handle(RoomMemberProfileAction.SetUserColorOverride(newColor)) } } .setNegativeButton(R.string.cancel, null) diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 5b07b101e7..8129dec3d4 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -28,22 +28,27 @@ import dagger.assisted.AssistedInject import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.extensions.exhaustive import im.vector.app.core.mvrx.runCatchingToAsync import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.displayname.getBestName +import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.powerlevel.PowerLevelsFlowFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams @@ -57,10 +62,12 @@ import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.flow.flow import org.matrix.android.sdk.flow.unwrap -class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private val initialState: RoomMemberProfileViewState, - private val stringProvider: StringProvider, - private val session: Session) : - VectorViewModel(initialState) { +class RoomMemberProfileViewModel @AssistedInject constructor( + @Assisted private val initialState: RoomMemberProfileViewState, + private val stringProvider: StringProvider, + private val matrixItemColorProvider: MatrixItemColorProvider, + private val session: Session +) : VectorViewModel(initialState) { @AssistedFactory interface Factory : MavericksAssistedViewModelFactory { @@ -85,6 +92,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v ) } observeIgnoredState() + observeAccountData() viewModelScope.launch(Dispatchers.Main) { // Do we have a room member for this id. val roomMember = withContext(Dispatchers.Default) { @@ -121,6 +129,24 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v } } + private fun observeAccountData() { + session.flow() + .liveUserAccountData(setOf(UserAccountDataTypes.TYPE_OVERRIDE_COLORS)) + .mapNotNull { it.firstOrNull() } + .map { it.content.toModel>() } + .map { userColorAccountDataContent -> + userColorAccountDataContent?.get(initialState.userId) + } + .onEach { + setState { + copy( + userColorOverride = it + ) + } + } + .launchIn(viewModelScope) + } + private fun observeIgnoredState() { session.flow().liveIgnoredUsers() .map { ignored -> @@ -143,6 +169,23 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v is RoomMemberProfileAction.BanOrUnbanUser -> handleBanOrUnbanAction(action) is RoomMemberProfileAction.KickUser -> handleKickAction(action) RoomMemberProfileAction.InviteUser -> handleInviteAction() + is RoomMemberProfileAction.SetUserColorOverride -> handleSetUserColorOverride(action) + }.exhaustive + } + + private fun handleSetUserColorOverride(action: RoomMemberProfileAction.SetUserColorOverride) { + val newOverrideColorSpecs = session.accountDataService().getUserAccountDataEvent(UserAccountDataTypes.TYPE_OVERRIDE_COLORS) + ?.content?.toMap().orEmpty().toMutableMap() + if (matrixItemColorProvider.setOverrideColor(initialState.userId, action.newColor)) { + newOverrideColorSpecs[initialState.userId] = action.newColor + } else { + newOverrideColorSpecs.remove(initialState.userId) + } + viewModelScope.launch { + session.accountDataService().updateUserAccountData( + type = UserAccountDataTypes.TYPE_OVERRIDE_COLORS, + content = newOverrideColorSpecs + ) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewState.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewState.kt index a4730153c2..1f2c3d6ce4 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewState.kt @@ -41,6 +41,7 @@ data class RoomMemberProfileViewState( val allDevicesAreCrossSignedTrusted: Boolean = false, val asyncMembership: Async = Uninitialized, val hasReadReceipt: Boolean = false, + val userColorOverride: String? = null, val actionPermissions: ActionPermissions = ActionPermissions() ) : MavericksState {