Merge pull request #188 from vector-im/feature/disambiguation

Disambiguation of display names
This commit is contained in:
Benoit Marty
2019-06-20 17:29:01 +02:00
committed by GitHub
27 changed files with 78 additions and 122 deletions

View File

@ -257,7 +257,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
try {
return Event(eventId = data["event_id"],
sender = data["sender"],
senderId = data["sender"],
roomId = data["room_id"],
type = data.getValue("type"),
// TODO content = data.getValue("content"),

View File

@ -222,8 +222,8 @@ class RoomDetailFragment :
}
//switch to expanded bar
composerLayout.composerRelatedMessageTitle.apply {
text = event.senderName
setTextColor(ContextCompat.getColor(requireContext(), getColorFromUserId(event.root.sender)))
text = event.getDisambiguatedDisplayName()
setTextColor(ContextCompat.getColor(requireContext(), getColorFromUserId(event.root.senderId)))
}
//TODO this is used at several places, find way to refactor?
@ -255,7 +255,7 @@ class RoomDetailFragment :
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_reply))
}
AvatarRenderer.render(event.senderAvatar, event.root.sender
AvatarRenderer.render(event.senderAvatar, event.root.senderId
?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)

View File

@ -282,7 +282,7 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
val dateFormat = SimpleDateFormat("EEE, d MMM yyyy HH:mm", Locale.getDefault())
_nonBlockingPopAlert.postValue(LiveEvent(
Pair(R.string.last_edited_info_message, listOf(
lastReplace.senderName ?: "?",
lastReplace.getDisambiguatedDisplayName(),
dateFormat.format(Date(lastReplace.root.originServerTs ?: 0)))
))
)
@ -429,7 +429,7 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
private fun observeInvitationState() {
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
if (summary.membership == Membership.INVITE) {
summary.lastMessage?.sender?.let { senderId ->
summary.lastMessage?.senderId?.let { senderId ->
session.getUser(senderId)
}?.also {
setState { copy(asyncInviter = Success(it)) }

View File

@ -238,7 +238,7 @@ class TimelineEventController(private val dateFormatter: TimelineDateFormatter,
val senderAvatar = mergedEvent.senderAvatar()
val senderName = mergedEvent.senderName()
MergedHeaderItem.Data(
userId = mergedEvent.root.sender ?: "",
userId = mergedEvent.root.senderId ?: "",
avatarUrl = senderAvatar,
memberName = senderName ?: "",
eventId = mergedEvent.localId

View File

@ -90,7 +90,7 @@ class MessageActionsViewModel(initialState: MessageActionState) : VectorViewMode
}
}
MessageActionState(
userId = event.root.sender ?: "",
userId = event.root.senderId ?: "",
senderName = parcel.informationData.memberName?.toString() ?: "",
messageBody = body,
ts = dateFormat.format(Date(originTs ?: 0)),

View File

@ -131,7 +131,7 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
}
this.add(SimpleAction(ACTION_COPY_PERMALINK, R.string.permalink, R.drawable.ic_permalink, parcel.eventId))
if (currentSession.sessionParams.credentials.userId != event.root.sender && event.root.getClearType() == EventType.MESSAGE) {
if (currentSession.sessionParams.credentials.userId != event.root.senderId && event.root.getClearType() == EventType.MESSAGE) {
//not sent by me
this.add(SimpleAction(ACTION_FLAG, R.string.report_content, R.drawable.ic_flag, parcel.eventId))
}
@ -179,7 +179,7 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
//Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
if (event.root.getClearType() != EventType.MESSAGE) return false
//TODO if user is admin or moderator
return event.root.sender == myUserId
return event.root.senderId == myUserId
}
private fun canViewReactions(event: TimelineEvent): Boolean {
@ -194,7 +194,7 @@ class MessageMenuViewModel(initialState: MessageMenuState) : VectorViewModel<Mes
if (event.root.getClearType() != EventType.MESSAGE) return false
//TODO if user is admin or moderator
val messageContent = event.root.content.toModel<MessageContent>()
return event.root.sender == myUserId && (
return event.root.senderId == myUserId && (
messageContent?.type == MessageType.MSGTYPE_TEXT
|| messageContent?.type == MessageType.MSGTYPE_EMOTE
)

View File

@ -49,8 +49,8 @@ class ViewReactionViewModel(private val session: Session,
sum.sourceEvents.mapNotNull { room.getTimeLineEvent(it) }.forEach {
val localDate = it.root.localDateTime()
results.add(ReactionInfo(it.root.eventId!!, sum.key, it.root.sender
?: "", it.senderName, timelineDateFormatter.formatMessageHour(localDate)))
results.add(ReactionInfo(it.root.eventId!!, sum.key, it.root.senderId
?: "", it.getDisambiguatedDisplayName(), timelineDateFormatter.formatMessageHour(localDate)))
}
}
setState {

View File

@ -37,7 +37,7 @@ class EncryptionItemFactory(private val stringProvider: StringProvider) {
val text = buildNoticeText(event.root, event.senderName) ?: return null
val informationData = MessageInformationData(
eventId = event.root.eventId ?: "?",
senderId = event.root.sender ?: "",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
avatarUrl = event.senderAvatar(),
memberName = event.senderName(),

View File

@ -32,7 +32,7 @@ class NoticeItemFactory(private val eventFormatter: NoticeEventFormatter) {
val formattedText = eventFormatter.format(event) ?: return null
val informationData = MessageInformationData(
eventId = event.root.eventId ?: "?",
senderId = event.root.sender ?: "",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
avatarUrl = event.senderAvatar(),
memberName = event.senderName(),

View File

@ -65,7 +65,7 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory,
if (TimelineDisplayableEvents.DEBUG_HIDDEN_EVENT) {
val informationData = MessageInformationData(eventId = event.root.eventId
?: "?",
senderId = event.root.sender ?: "",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
time = "",
avatarUrl = null,

View File

@ -32,13 +32,13 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
fun format(timelineEvent: TimelineEvent): CharSequence? {
return when (val type = timelineEvent.root.getClearType()) {
EventType.STATE_ROOM_NAME -> formatRoomNameEvent(timelineEvent.root, timelineEvent.senderName)
EventType.STATE_ROOM_TOPIC -> formatRoomTopicEvent(timelineEvent.root, timelineEvent.senderName)
EventType.STATE_ROOM_NAME -> formatRoomNameEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
EventType.STATE_ROOM_TOPIC -> formatRoomTopicEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
EventType.STATE_ROOM_MEMBER -> formatRoomMemberEvent(timelineEvent.root, timelineEvent.senderName())
EventType.STATE_HISTORY_VISIBILITY -> formatRoomHistoryVisibilityEvent(timelineEvent.root, timelineEvent.senderName)
EventType.STATE_HISTORY_VISIBILITY -> formatRoomHistoryVisibilityEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
EventType.CALL_INVITE,
EventType.CALL_HANGUP,
EventType.CALL_ANSWER -> formatCallEvent(timelineEvent.root, timelineEvent.senderName)
EventType.CALL_ANSWER -> formatCallEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
else -> {
Timber.v("Type $type not handled by this formatter")
null
@ -111,12 +111,12 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
if (!TextUtils.equals(eventContent?.displayName, prevEventContent?.displayName)) {
val displayNameText = when {
prevEventContent?.displayName.isNullOrEmpty() ->
stringProvider.getString(R.string.notice_display_name_set, event.sender, eventContent?.displayName)
stringProvider.getString(R.string.notice_display_name_set, event.senderId, eventContent?.displayName)
eventContent?.displayName.isNullOrEmpty() ->
stringProvider.getString(R.string.notice_display_name_removed, event.sender, prevEventContent?.displayName)
stringProvider.getString(R.string.notice_display_name_removed, event.senderId, prevEventContent?.displayName)
else ->
stringProvider.getString(R.string.notice_display_name_changed_from,
event.sender, prevEventContent?.displayName, eventContent?.displayName)
event.senderId, prevEventContent?.displayName, eventContent?.displayName)
}
displayText.append(displayNameText)
}
@ -134,8 +134,8 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
}
private fun buildMembershipNotice(event: Event, senderName: String?, eventContent: RoomMember?, prevEventContent: RoomMember?): String? {
val senderDisplayName = senderName ?: event.sender
val targetDisplayName = eventContent?.displayName ?: event.sender
val senderDisplayName = senderName ?: event.senderId
val targetDisplayName = eventContent?.displayName ?: event.senderId
return when {
Membership.INVITE == eventContent?.membership -> {
// TODO get userId
@ -156,7 +156,7 @@ class NoticeEventFormatter(private val stringProvider: StringProvider) {
stringProvider.getString(R.string.notice_room_join, senderDisplayName)
Membership.LEAVE == eventContent?.membership ->
// 2 cases here: this member may have left voluntarily or they may have been "left" by someone else ie. kicked
return if (TextUtils.equals(event.sender, event.stateKey)) {
return if (TextUtils.equals(event.senderId, event.stateKey)) {
if (prevEventContent?.membership == Membership.INVITE) {
stringProvider.getString(R.string.notice_room_reject, senderDisplayName)
} else {

View File

@ -85,12 +85,11 @@ fun TimelineEvent.senderAvatar(): String? {
fun TimelineEvent.senderName(): String? {
// We might have no senderName when user leave, so we try to get it from prevContent
return senderName
?: if (root.type == EventType.STATE_ROOM_MEMBER) {
root.prevContent.toModel<RoomMember>()?.displayName
} else {
null
}
return when {
senderName != null -> getDisambiguatedDisplayName()
root.type == EventType.STATE_ROOM_MEMBER -> root.prevContent.toModel<RoomMember>()?.displayName
else -> null
}
}
fun TimelineEvent.canBeMerged(): Boolean {

View File

@ -83,7 +83,6 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
override fun bind(holder: H) {
super.bind(holder)
if (informationData.showInformation) {
holder.avatarImageView.layoutParams = holder.avatarImageView.layoutParams?.apply {
val size = dpToPx(avatarStyle.avatarSizeDP, holder.view.context)
height = size

View File

@ -22,7 +22,6 @@ import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.resources.ColorProvider
import im.vector.riotredesign.features.home.getColorFromUserId
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.riotredesign.features.home.room.detail.timeline.item.ReactionInfoData
import me.gujun.android.span.span
@ -38,23 +37,23 @@ class MessageInformationDataFactory(private val timelineDateFormatter: TimelineD
val eventId = event.root.eventId!!
val date = event.root.localDateTime()
val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
?: false
val showInformation =
addDaySeparator
|| event.senderAvatar != nextEvent?.senderAvatar
|| event.senderName != nextEvent?.senderName
|| event.getDisambiguatedDisplayName() != nextEvent?.getDisambiguatedDisplayName()
|| (nextEvent?.root?.getClearType() != EventType.MESSAGE && nextEvent?.root?.getClearType() != EventType.ENCRYPTED)
|| isNextMessageReceivedMoreThanOneHourAgo
val time = timelineDateFormatter.formatMessageHour(date)
val avatarUrl = event.senderAvatar()
val memberName = event.senderName ?: event.root.sender ?: ""
val avatarUrl = event.senderAvatar
val memberName = event.getDisambiguatedDisplayName()
val formattedMemberName = span(memberName) {
textColor = colorProvider.getColor(getColorFromUserId(event.root.sender
textColor = colorProvider.getColor(getColorFromUserId(event.root.senderId
?: ""))
}
@ -62,7 +61,7 @@ class MessageInformationDataFactory(private val timelineDateFormatter: TimelineD
return MessageInformationData(
eventId = eventId,
senderId = event.root.sender ?: "",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
time = time,
avatarUrl = avatarUrl,