Allow custom emote packs with state keys

Fixes https://github.com/SchildiChat/SchildiChat-android/issues/184

Change-Id: I79ede7f9b45ff762b367c4b5cd048987e4f25515
This commit is contained in:
SpiritCroc 2023-01-15 13:11:50 +01:00
parent 1f7ff4aec7
commit e3a7ef911e
1 changed files with 43 additions and 22 deletions

View File

@ -33,6 +33,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
@ -91,7 +92,7 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
}.toAutocompleteItems() }.toAutocompleteItems()
// Custom emotes: This room's emotes // Custom emotes: This room's emotes
val currentRoomEmotes = room.getEmojiItems(query) val currentRoomEmotes = room.getAllEmojiItems(query)
val emoteData = currentRoomEmotes.toAutocompleteItems().let { val emoteData = currentRoomEmotes.toAutocompleteItems().let {
if (it.isNotEmpty()) { if (it.isNotEmpty()) {
listOf(AutocompleteEmojiDataItem.Header(roomId, context.getString(R.string.custom_emotes_this_room))) + it listOf(AutocompleteEmojiDataItem.Header(roomId, context.getString(R.string.custom_emotes_this_room))) + it
@ -109,10 +110,12 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
.limit(AutocompleteEmojiController.CUSTOM_ACCOUNT_MAX) .limit(AutocompleteEmojiController.CUSTOM_ACCOUNT_MAX)
if (userPack.isNotEmpty()) { if (userPack.isNotEmpty()) {
emoteUrls.addAll(userPack.map { it.mxcUrl }) emoteUrls.addAll(userPack.map { it.mxcUrl })
emoteData += listOf(AutocompleteEmojiDataItem.Header( emoteData += listOf(
AutocompleteEmojiDataItem.Header(
"de.spiritcroc.riotx.ACCOUNT_EMOJI_HEADER", "de.spiritcroc.riotx.ACCOUNT_EMOJI_HEADER",
context.getString(R.string.custom_emotes_account_data) context.getString(R.string.custom_emotes_account_data)
)) )
)
emoteData += userPack.toAutocompleteItems() emoteData += userPack.toAutocompleteItems()
} }
// Global emotes from rooms // Global emotes from rooms
@ -120,7 +123,8 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
var packsAdded = 0 var packsAdded = 0
(globalPacks?.content?.get("rooms") as? Map<*, *>)?.forEach { pack -> (globalPacks?.content?.get("rooms") as? Map<*, *>)?.forEach { pack ->
// If entry is empty, it has been disabled as global pack (after being enabled before). // If entry is empty, it has been disabled as global pack (after being enabled before).
if ((pack.value as? Map<*, *>).isNullOrEmpty()) { val packsEnabled = pack.value as? Map<*, *>
if (packsEnabled.isNullOrEmpty()) {
return@forEach return@forEach
} }
if (packsAdded >= AutocompleteEmojiController.MAX_CUSTOM_OTHER_ROOMS) { if (packsAdded >= AutocompleteEmojiController.MAX_CUSTOM_OTHER_ROOMS) {
@ -129,24 +133,31 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
val packRoomId = pack.key val packRoomId = pack.key
if (packRoomId is String && packRoomId != roomId) { if (packRoomId is String && packRoomId != roomId) {
val packRoom = session.getRoom(packRoomId) ?: return@forEach val packRoom = session.getRoom(packRoomId) ?: return@forEach
packsEnabled.forEach roomPack@{ roomPack ->
val packId = roomPack.key as? String ?: return@roomPack
// Filter out duplicate emotes with the exact same mxc url // Filter out duplicate emotes with the exact same mxc url
val packImages = packRoom.getEmojiItems(query).filter { val packImages = packRoom.getEmojiItems(query, QueryStringValue.Equals(packId)).filter {
it.mxcUrl !in emoteUrls it.mxcUrl !in emoteUrls
}.limit(AutocompleteEmojiController.CUSTOM_OTHER_ROOM_MAX) }.limit(AutocompleteEmojiController.CUSTOM_OTHER_ROOM_MAX)
// Add header + emotes // Add header + emotes
if (packImages.isNotEmpty()) { if (packImages.isNotEmpty()) {
packsAdded++ packsAdded++
emoteUrls.addAll(packImages.map { it.mxcUrl }) emoteUrls.addAll(packImages.map { it.mxcUrl })
emoteData += listOf(AutocompleteEmojiDataItem.Header( emoteData += listOf(
AutocompleteEmojiDataItem.Header(
packRoomId, packRoomId,
context.getString(R.string.custom_emotes_other_room, context.getString(
packRoom.roomSummary()?.displayName ?: packRoomId) R.string.custom_emotes_other_room,
)) packRoom.roomSummary()?.displayName ?: packRoomId
)
)
)
emoteData += packImages.toAutocompleteItems() emoteData += packImages.toAutocompleteItems()
} }
} }
} }
} }
}
val dataHeader = if (data.isNotEmpty() && emoteData.isNotEmpty()) { val dataHeader = if (data.isNotEmpty() && emoteData.isNotEmpty()) {
listOf(AutocompleteEmojiDataItem.Header("de.spiritcroc.riotx.STANDARD_EMOJI_HEADER", context.getString(R.string.standard_emojis))) listOf(AutocompleteEmojiDataItem.Header("de.spiritcroc.riotx.STANDARD_EMOJI_HEADER", context.getString(R.string.standard_emojis)))
@ -161,8 +172,18 @@ class AutocompleteEmojiPresenter @AssistedInject constructor(
return map { AutocompleteEmojiDataItem.Emoji(it) } return map { AutocompleteEmojiDataItem.Emoji(it) }
} }
private fun Room.getEmojiItems(query: CharSequence?): List<EmojiItem> { private fun Room.getEmojiItems(query: CharSequence?, queryStringValue: QueryStateEventValue): List<EmojiItem> {
return getStateEvent(EventType.ROOM_EMOTES, QueryStringValue.IsEmpty)?.content?.toModel<RoomEmoteContent>().getEmojiItems(query) return getStateEvent(EventType.ROOM_EMOTES, queryStringValue)?.content?.toModel<RoomEmoteContent>().getEmojiItems(query)
}
private fun Room.getAllEmojiItems(query: CharSequence?): List<EmojiItem> {
// NoCondition isn't allowed by matrix sdk for getStateEvents, so query both empty and non-empty
val eventTypeList = setOf(EventType.ROOM_EMOTES)
val emptyItems = stateService().getStateEvents(eventTypeList, QueryStringValue.IsEmpty)
val keyedItems = stateService().getStateEvents(eventTypeList, QueryStringValue.IsNotEmpty)
return (emptyItems + keyedItems).flatMap {
it.content?.toModel<RoomEmoteContent>().getEmojiItems(query)
}
} }
private fun RoomEmoteContent?.getEmojiItems(query: CharSequence?): List<EmojiItem> { private fun RoomEmoteContent?.getEmojiItems(query: CharSequence?): List<EmojiItem> {