Skip to content

[issue-2610] implement setting to override nick color #2614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7aaebd4
[issue-2610] implement setting to override nick color
mitchnull Jan 3, 2021
889a9a1
[issue-2610] fix NoSuchElement error
mitchnull Jan 3, 2021
0aee15f
[issue-2610] Merge branch 'develop' of github.com:mitchnull/element-a…
mitchnull Jan 20, 2021
0e400dc
[issue-2610] Add Override Color menu item under More...
mitchnull Feb 3, 2021
0109cde
[issue-2610] Merge branch 'develop' of https://github.com/vector-im/e…
mitchnull Feb 3, 2021
f7d8127
[issue-2610] remove extra semicolon
mitchnull Feb 3, 2021
cc15f9b
[issue-2610] remove click handler from display-name
mitchnull Feb 6, 2021
db97046
[issue-2610] change menu text to "Override nick color"
mitchnull Feb 13, 2021
da10364
[issue-2610] Merge branch 'develop' of https://github.com/vector-im/e…
mitchnull Feb 13, 2021
6c26cfc
[issue-2610] Merge branch 'develop' of https://github.com/vector-im/e…
mitchnull Feb 16, 2021
ea01677
[issue-2610] Merge branch 'develop' of https://github.com/vector-im/e…
mitchnull Feb 18, 2021
1ec0956
[issue-2610] Merge branch 'develop' of https://github.com/vector-im/e…
mitchnull Feb 20, 2021
1019ffe
[issue-2610-override-nick-color-via-user-account-data] [issue-2610] M…
mitchnull Apr 12, 2021
40d48cc
[issue-2610-override-nick-color-via-user-account-data] Merge branch '…
mitchnull May 9, 2021
79a3be3
[issue-2610] Merge branch 'develop' of github.com:mitchnull/element-a…
mitchnull May 19, 2021
bf919b8
[issue-2610] Merge branch 'develop' of github.com:mitchnull/element-a…
mitchnull Aug 15, 2021
454baf8
Merge branch 'develop' into feature/issue-2610-override-nick-color-vi…
bmarty Dec 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ Changes in Element 1.1.7 (2021-05-12)
===================================================

Features ✨:
- Allow changing nick colors (#2610)
- Spaces beta

Improvements 🙌:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ object UserAccountDataTypes {
const val TYPE_ALLOWED_WIDGETS = "im.vector.setting.allowed_widgets"
const val TYPE_IDENTITY_SERVER = "m.identity_server"
const val TYPE_ACCEPTED_TERMS = "m.accepted_terms"
const val TYPE_OVERRIDE_COLORS = "im.vector.setting.override_colors"
}
29 changes: 29 additions & 0 deletions vector/src/main/java/im/vector/app/AppStateHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ import androidx.lifecycle.LifecycleOwner
import arrow.core.Option
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.ui.UiStateRepository
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
Expand All @@ -33,8 +38,11 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
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.toModel
import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.rx.rx
import javax.inject.Inject
import javax.inject.Singleton

Expand All @@ -54,6 +62,7 @@ fun RoomGroupingMethod.group() = (this as? RoomGroupingMethod.ByLegacyGroup)?.gr
@Singleton
class AppStateHandler @Inject constructor(
private val sessionDataSource: ActiveSessionDataSource,
private val matrixItemColorProvider: MatrixItemColorProvider,
private val uiStateRepository: UiStateRepository,
private val activeSessionHolder: ActiveSessionHolder
) : DefaultLifecycleObserver {
Expand Down Expand Up @@ -132,6 +141,11 @@ class AppStateHandler @Inject constructor(
return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
}

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun entersForeground() {
observeUserAccountData()
}

override fun onResume(owner: LifecycleOwner) {
observeActiveSession()
}
Expand All @@ -150,4 +164,19 @@ class AppStateHandler @Inject constructor(
}
}
}

private fun observeUserAccountData() {
sessionDataSource.observe()
.observeOn(AndroidSchedulers.mainThread())
.switchMap {
it.orNull()?.rx()?.liveUserAccountData(setOf(UserAccountDataTypes.TYPE_OVERRIDE_COLORS))
?: Observable.just(emptyList())
}
.distinctUntilChanged()
.subscribe {
val overrideColorSpecs = it?.firstOrNull()?.content?.toModel<Map<String, String>>()
matrixItemColorProvider.setOverrideColors(overrideColorSpecs)
}
.addTo(compositeDisposable)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,39 @@ class MatrixItemColorProvider @Inject constructor(
}
}

fun setOverrideColors(overrideColors: Map<String, String>?) {
overrideColors?.forEach() {
setOverrideColor(it.key, it.value)
}
}

fun setOverrideColor(id: String, colorSpec: String?) : Boolean {
val color = parseUserColorSpec(colorSpec)
if (color == null) {
cache.remove(id)
return false
} else {
cache.put(id, color)
return true
}
}

@ColorInt
private fun parseUserColorSpec(colorText: String?): Int? {
if (colorText.isNullOrBlank()) {
return null
}
try {
if (colorText.first() == '#') {
return (colorText.substring(1).toLong(radix = 16) or 0xff000000L).toInt()
} else {
return colorProvider.getColor(getUserColorByIndex(colorText.toInt()))
}
} catch (e: Throwable) {
return null
}
}

companion object {
@ColorRes
@VisibleForTesting
Expand All @@ -52,7 +85,12 @@ class MatrixItemColorProvider @Inject constructor(

userId?.toList()?.map { chr -> hash = (hash shl 5) - hash + chr.code }

return when (abs(hash) % 8) {
return getUserColorByIndex(abs(hash))
}

@ColorRes
private fun getUserColorByIndex(index: Int): Int {
return when (index % 8) {
1 -> R.color.element_name_02
2 -> R.color.element_name_03
3 -> R.color.element_name_04
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class RoomMemberProfileController @Inject constructor(
fun onShowDeviceList()
fun onShowDeviceListNoCrossSigning()
fun onOpenDmClicked()
fun onOverrideColorClicked()
fun onJumpToReadReceiptClicked()
fun onMentionClicked()
fun onEditPowerLevel(currentRole: Role)
Expand Down Expand Up @@ -171,11 +172,19 @@ class RoomMemberProfileController @Inject constructor(

private fun buildMoreSection(state: RoomMemberProfileViewState) {
// More
buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))

buildProfileAction(
id = "overrideColor",
editable = false,
title = stringProvider.getString(R.string.room_member_override_nick_color),
divider = false,
action = { callback?.onOverrideColorClicked() }
)

if (!state.isMine) {
val membership = state.asyncMembership() ?: return

buildProfileSection(stringProvider.getString(R.string.room_profile_section_more))

buildProfileAction(
id = "direct",
editable = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ 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
Expand All @@ -43,6 +44,7 @@ import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.platform.StateView
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.startSharePlainTextIntent
import im.vector.app.databinding.DialogBaseEditTextBinding
import im.vector.app.databinding.DialogShareQrCodeBinding
import im.vector.app.databinding.FragmentMatrixProfileBinding
import im.vector.app.databinding.ViewStubRoomMemberProfileHeaderBinding
Expand All @@ -51,10 +53,13 @@ import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.RoomDetailPendingAction
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
Expand All @@ -68,7 +73,8 @@ data class RoomMemberProfileArgs(
class RoomMemberProfileFragment @Inject constructor(
private val roomMemberProfileController: RoomMemberProfileController,
private val avatarRenderer: AvatarRenderer,
private val roomDetailPendingActionStore: RoomDetailPendingActionStore
private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
private val matrixItemColorProvider: MatrixItemColorProvider
) : VectorBaseFragment<FragmentMatrixProfileBinding>(),
RoomMemberProfileController.Callback {

Expand Down Expand Up @@ -200,6 +206,7 @@ class RoomMemberProfileFragment @Inject constructor(
headerViews.memberProfileIdView.text = userMatrixItem.id
val bestName = userMatrixItem.getBestName()
headerViews.memberProfileNameView.text = bestName
headerViews.memberProfileNameView.setTextColor(matrixItemColorProvider.getColor(userMatrixItem))
views.matrixProfileToolbarTitleView.text = bestName
avatarRenderer.render(userMatrixItem, headerViews.memberProfileAvatarView)
avatarRenderer.render(userMatrixItem, views.matrixProfileToolbarAvatarImageView)
Expand Down Expand Up @@ -321,6 +328,42 @@ class RoomMemberProfileFragment @Inject constructor(
navigator.openBigImageViewer(requireActivity(), view, userMatrixItem)
}

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.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()
}
}
.setNegativeButton(R.string.cancel, null)
.show()
}

override fun onEditPowerLevel(currentRole: Role) {
EditPowerLevelDialogs.showChoice(requireActivity(), R.string.power_level_edit_title, currentRole) { newPowerLevel ->
viewModel.handle(RoomMemberProfileAction.SetPowerLevel(currentRole.value, newPowerLevel, true))
Expand Down
2 changes: 2 additions & 0 deletions vector/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2812,6 +2812,8 @@
<string name="direct_room_profile_section_more_leave">Leave</string>
<string name="room_profile_leaving_room">"Leaving the room…"</string>

<string name="room_member_override_nick_color">Override nick color</string>

<string name="room_member_power_level_admins">Admins</string>
<string name="room_member_power_level_moderators">Moderators</string>
<string name="room_member_power_level_custom">Custom</string>
Expand Down