Adding autocomplete for @room (missing correct first letter of avatar)

This commit is contained in:
Maxime Naturel 2022-02-10 17:22:29 +01:00
parent 38fdfb27e4
commit d8e28d7be9
5 changed files with 87 additions and 22 deletions

View file

@ -27,7 +27,6 @@ import org.matrix.android.sdk.api.session.room.sender.SenderInfo
import org.matrix.android.sdk.api.session.user.model.User
import java.util.Locale
// TODO how to represent the notify everyone @room item? EveryoneItem ??
sealed class MatrixItem(
open val id: String,
open val displayName: String?,
@ -36,7 +35,18 @@ sealed class MatrixItem(
data class UserItem(override val id: String,
override val displayName: String? = null,
override val avatarUrl: String? = null) :
MatrixItem(id, displayName?.removeSuffix(ircPattern), avatarUrl) {
MatrixItem(id, displayName?.removeSuffix(IRC_PATTERN), avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
}
override fun updateAvatar(newAvatar: String?) = copy(avatarUrl = newAvatar)
}
data class EveryoneInRoomItem(override val id: String,
override val displayName: String? = null,
override val avatarUrl: String? = null) :
MatrixItem(id, displayName, avatarUrl) {
init {
if (BuildConfig.DEBUG) checkId()
}
@ -110,16 +120,18 @@ sealed class MatrixItem(
/**
* Return the prefix as defined in the matrix spec (and not extracted from the id)
*/
fun getIdPrefix() = when (this) {
private fun getIdPrefix() = when (this) {
is UserItem -> '@'
is EventItem -> '$'
is SpaceItem,
is RoomItem -> '!'
is RoomItem,
is EveryoneInRoomItem -> '!'
is RoomAliasItem -> '#'
is GroupItem -> '+'
}
fun firstLetterOfDisplayName(): String {
// TODO retrieve first letter of room name when EveryoneInRoomItem
return (displayName?.takeIf { it.isNotBlank() } ?: id)
.let { dn ->
var startIndex = 0
@ -152,7 +164,8 @@ sealed class MatrixItem(
}
companion object {
private const val ircPattern = " (IRC)"
private const val IRC_PATTERN = " (IRC)"
const val NOTIFY_EVERYONE = "@room"
}
}
@ -172,6 +185,8 @@ fun RoomSummary.toMatrixItem() = if (roomType == RoomType.SPACE) {
fun RoomSummary.toRoomAliasMatrixItem() = MatrixItem.RoomAliasItem(canonicalAlias ?: roomId, displayName, avatarUrl)
fun RoomSummary.toEveryoneInRoomMatrixItem() = MatrixItem.EveryoneInRoomItem(roomId, MatrixItem.NOTIFY_EVERYONE, avatarUrl)
// If no name is available, use room alias as Riot-Web does
fun PublicRoom.toMatrixItem() = MatrixItem.RoomItem(roomId, name ?: getPrimaryAlias() ?: "", avatarUrl)

View file

@ -16,19 +16,35 @@
package im.vector.app.features.autocomplete.member
import android.content.Context
import com.airbnb.epoxy.TypedEpoxyController
import im.vector.app.R
import im.vector.app.features.autocomplete.AutocompleteClickListener
import im.vector.app.features.autocomplete.autocompleteMatrixItem
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<List<AutocompleteMemberItem>>() {
class AutocompleteMemberController @Inject constructor(private val context: Context)
: TypedEpoxyController<List<AutocompleteMemberItem>>() {
///////////////////////////////////////////////////////////////////////////
// FIELDS
///////////////////////////////////////////////////////////////////////////
var listener: AutocompleteClickListener<AutocompleteMemberItem>? = null
///////////////////////////////////////////////////////////////////////////
// DEPENDENCIES
///////////////////////////////////////////////////////////////////////////
@Inject lateinit var avatarRenderer: AvatarRenderer
///////////////////////////////////////////////////////////////////////////
// SPECIALIZATION
///////////////////////////////////////////////////////////////////////////
override fun buildModels(data: List<AutocompleteMemberItem>?) {
if (data.isNullOrEmpty()) {
return
@ -46,17 +62,30 @@ class AutocompleteMemberController @Inject constructor() : TypedEpoxyController<
///////////////////////////////////////////////////////////////////////////
private fun buildRoomMemberItem(roomMember: AutocompleteMemberItem.RoomMember) {
val host = this
autocompleteMatrixItem {
roomMember.roomMemberSummary.let { user ->
id(user.userId)
matrixItem(user.toMatrixItem())
avatarRenderer(this@AutocompleteMemberController.avatarRenderer)
clickListener { this@AutocompleteMemberController.listener?.onItemClick(roomMember) }
avatarRenderer(host.avatarRenderer)
clickListener { host.listener?.onItemClick(roomMember) }
}
}
}
private fun buildEveryoneItem(everyone: AutocompleteMemberItem.Everyone) {
// TODO
val host = this
autocompleteMatrixItem {
everyone.roomSummary.let { room ->
id(room.roomId)
matrixItem(room.toEveryoneInRoomMatrixItem())
subName(host.context.getString(R.string.room_message_notify_everyone))
// TODO fix usage of first letter of room name when avatarUrl is empty
// TODO test avatar with a room which has a picture
avatarRenderer(host.avatarRenderer)
clickListener { host.listener?.onItemClick(everyone) }
}
}
}
}

View file

@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.Session
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.model.RoomMemberSummary
import org.matrix.android.sdk.api.util.MatrixItem
class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
@Assisted val roomId: String,
@ -68,14 +69,28 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
memberships = listOf(Membership.JOIN)
excludeSelf = true
}
val members = room.getRoomMembers(queryParams)
.asSequence()
.sortedBy { it.displayName }
.disambiguate()
.map { AutocompleteMemberItem.RoomMember(it) }
.toList()
// TODO check if user can notify everyone => compare user role to room permission setting: PowerLevelsContent
// TODO if user can notify everyone, add entry AutocompleteMemberItem.Everyone
// TODO add header sections to separate members and notification
controller.setData(members.map { AutocompleteMemberItem.RoomMember(it) }.toList())
val everyone = room.roomSummary()
?.takeIf { query.isNullOrBlank() || MatrixItem.NOTIFY_EVERYONE.startsWith("@$query") }
?.let {
AutocompleteMemberItem.Everyone(it)
}
val items = mutableListOf<AutocompleteMemberItem>().apply {
// TODO add header sections
addAll(members)
everyone?.let { add(it) }
}
controller.setData(items)
}
}

View file

@ -44,6 +44,7 @@ import im.vector.app.features.themes.ThemeUtils
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.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.api.util.toRoomAliasMatrixItem
@ -135,7 +136,8 @@ class AutoCompleter @AssistedInject constructor(
when (item) {
is AutocompleteMemberItem.RoomMember ->
insertMatrixItem(editText, editable, "@", item.roomMemberSummary.toMatrixItem())
is AutocompleteMemberItem.Everyone -> Unit // TODO
is AutocompleteMemberItem.Everyone ->
insertMatrixItem(editText, editable, "@", item.roomSummary.toEveryoneInRoomMatrixItem())
}
return true
}
@ -253,6 +255,7 @@ class AutoCompleter @AssistedInject constructor(
}
companion object {
// TODO add consts for string trigger for autocomplete
private const val ELEVATION = 6f
}
}

View file

@ -3782,4 +3782,7 @@
<string name="message_reaction_show_less">Show less</string>
<string name="message_reaction_show_more">"%1$d more"</string>
<string name="room_message_notify_everyone">Notify the whole room</string>
<string name="room_message_autocomplete_users">Users</string>
<string name="room_message_autocomplete_notification">Room notification</string>
</resources>