Skip to content

Commit 358008c

Browse files
committed
chore(fc): improve performance loading chats; tweak deleted message body styling
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 6d608bd commit 358008c

File tree

6 files changed

+169
-94
lines changed

6 files changed

+169
-94
lines changed

flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationViewModel.kt

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import kotlinx.coroutines.flow.mapNotNull
5757
import kotlinx.coroutines.flow.onEach
5858
import kotlinx.coroutines.flow.take
5959
import kotlinx.coroutines.launch
60+
import kotlinx.datetime.Clock
6061
import kotlinx.datetime.Instant
6162
import timber.log.Timber
6263
import xyz.flipchat.app.R
@@ -78,6 +79,7 @@ import xyz.flipchat.services.domain.model.chat.ConversationMember
7879
import xyz.flipchat.services.domain.model.chat.ConversationMessage
7980
import xyz.flipchat.services.domain.model.chat.ConversationWithMembersAndLastPointers
8081
import xyz.flipchat.services.extensions.titleOrFallback
82+
import xyz.flipchat.services.internal.data.mapper.nullIfEmpty
8183
import xyz.flipchat.services.user.AuthState
8284
import xyz.flipchat.services.user.UserManager
8385
import java.util.UUID
@@ -818,67 +820,63 @@ class ConversationViewModel @Inject constructor(
818820
.filterNotNull()
819821
.distinctUntilChanged()
820822
.flatMapLatest { roomController.messages(it).flow }
823+
.distinctUntilChanged()
821824
.map { page ->
822825
val currentState = stateFlow.value // Cache state upfront
823826
val pointerRefs = currentState.pointerRefs // cache expensive pointer ref map upfront
824827
val enableReply =
825828
currentState.replyEnabled && currentState.chattableState is ChattableState.Enabled
826829

827830
page.map { indice ->
828-
val (message, member, contents) = indice
831+
val (message, member, contents, reply, tipInfo) = indice
829832

830833
val status = findClosestMessageStatus(
831834
timestamp = message.id.uuid?.timestamp,
832835
statusMap = pointerRefs,
833836
fallback = if (contents.isFromSelf) MessageStatus.Sent else MessageStatus.Unknown
834837
)
835838

836-
val anchor = if (contents is MessageContent.Reply) {
837-
val originalMessage = roomController.getMessage(contents.originalMessageId)
838-
originalMessage?.let { container ->
839-
ReplyMessageAnchor(
840-
id = contents.originalMessageId,
841-
message = container.content,
842-
isDeleted = container.message.isDeleted,
843-
deletedBy = container.message.deletedBy?.let { id ->
844-
Deleter(
845-
id = id,
846-
isSelf = userManager.isSelf(id),
847-
isHost = currentState.hostId == message.deletedBy
848-
)
849-
},
850-
sender = Sender(
851-
id = container.message.senderId,
852-
profileImage = container.member?.imageUri.takeIf {
853-
it.orEmpty().isNotEmpty()
854-
},
855-
displayName = container.member?.memberName ?: "Deleted",
856-
isSelf = container.content.isFromSelf,
857-
isBlocked = container.member?.isBlocked == true,
858-
isHost = container.message.senderId == currentState.hostId && !contents.isFromSelf,
839+
val anchor = if (reply != null) {
840+
ReplyMessageAnchor(
841+
id = reply.message.id,
842+
message = reply.content,
843+
isDeleted = reply.message.isDeleted,
844+
deletedBy = reply.message.deletedBy?.let { id ->
845+
Deleter(
846+
id = id,
847+
isSelf = userManager.isSelf(id),
848+
isHost = currentState.hostId == message.deletedBy
859849
)
850+
},
851+
sender = Sender(
852+
id = reply.message.senderId,
853+
profileImage = reply.member?.imageUri.takeIf {
854+
it.orEmpty().isNotEmpty()
855+
},
856+
displayName = reply.member?.memberName ?: "Deleted",
857+
isSelf = reply.content.isFromSelf,
858+
isBlocked = reply.member?.isBlocked == true,
859+
isHost = reply.message.senderId == currentState.hostId && !contents.isFromSelf,
860860
)
861-
}
861+
)
862862
} else {
863863
null
864864
}
865865

866866
val tippingEnabled =
867867
currentState.isTippingEnabled && !userManager.isSelf(message.senderId)
868868

869-
val tips = if (currentState.isTippingEnabled) {
870-
roomController.getTipsForMessage(message.id).map { tip ->
871-
val amount = KinAmount.fromQuarks(tip.amountInQuarks)
872-
val tipper = roomController.getMemberForId(tip.tipperId)
869+
val tips = if (currentState.isTippingEnabled && tipInfo.isNotEmpty()) {
870+
tipInfo.map { (amount, member) ->
873871
MessageTip(
874872
amount = amount,
875873
tipper = Sender(
876-
id = tip.tipperId,
877-
profileImage = tipper?.imageUri,
878-
displayName = tipper?.memberName,
879-
isHost = tipper?.isHost ?: false,
880-
isSelf = userManager.isSelf(tip.tipperId),
881-
isBlocked = tipper?.isBlocked ?: false,
874+
id = member?.id,
875+
profileImage = member?.imageUri.nullIfEmpty(),
876+
displayName = member?.memberName,
877+
isHost = member?.isHost ?: false,
878+
isSelf = userManager.isSelf(member?.id),
879+
isBlocked = member?.isBlocked ?: false,
882880
)
883881
)
884882
}
@@ -911,7 +909,7 @@ class ConversationViewModel @Inject constructor(
911909
profileImage = member?.imageUri.takeIf { it.orEmpty().isNotEmpty() },
912910
displayName = member?.memberName ?: "Deleted",
913911
isSelf = contents.isFromSelf,
914-
isHost = message.senderId == currentState.hostId && !contents.isFromSelf,
912+
isHost = member?.isHost ?: false,
915913
isBlocked = member?.isBlocked == true,
916914
),
917915
originalMessage = anchor,

services/flipchat/chat/src/main/kotlin/xyz/flipchat/services/domain/model/chat/ConversationMessage.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import androidx.room.Index
88
import androidx.room.PrimaryKey
99
import androidx.room.Relation
1010
import com.getcode.model.ID
11+
import com.getcode.model.KinAmount
1112
import com.getcode.model.chat.MessageContent
13+
import com.getcode.model.chat.Sender
1214
import com.getcode.vendor.Base58
1315
import kotlinx.serialization.Serializable
1416

@@ -63,8 +65,33 @@ data class ConversationMessageWithMember(
6365
val member: ConversationMember?
6466
)
6567

68+
data class ConversationMessageWithMemberAndReplyAndTips(
69+
@Embedded val message: ConversationMessage,
70+
@Relation(
71+
parentColumn = "senderIdBase58",
72+
entityColumn = "memberIdBase58",
73+
entity = ConversationMember::class,
74+
)
75+
val member: ConversationMember?,
76+
val reply: ConversationMessageWithMemberAndContent?,
77+
val tips: List<MessageTipInfo>
78+
)
79+
6680
data class ConversationMessageWithMemberAndContent(
6781
@Embedded val message: ConversationMessage,
6882
val member: ConversationMember?,
6983
val content: MessageContent
84+
)
85+
86+
data class ConversationMessageWithMemberAndContentAndReplyAndTips(
87+
val message: ConversationMessage,
88+
val member: ConversationMember?,
89+
val content: MessageContent,
90+
val reply: ConversationMessageWithMemberAndContent?,
91+
val tips: List<MessageTipInfo>
92+
)
93+
94+
data class MessageTipInfo(
95+
val kinAmount: KinAmount,
96+
val tipper: ConversationMember?
7097
)

services/flipchat/chat/src/main/kotlin/xyz/flipchat/services/internal/db/ConversationMessageDao.kt

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package xyz.flipchat.services.internal.db
22

3+
import androidx.paging.PagingSource
34
import androidx.room.Dao
45
import androidx.room.Insert
56
import androidx.room.OnConflictStrategy
67
import androidx.room.Query
78
import androidx.room.RewriteQueriesToDropUnusedColumns
89
import androidx.room.Transaction
910
import com.getcode.model.ID
11+
import com.getcode.model.KinAmount
1012
import com.getcode.model.chat.MessageContent
1113
import com.getcode.utils.base58
14+
import xyz.flipchat.services.domain.model.chat.ConversationMember
1215
import xyz.flipchat.services.domain.model.chat.ConversationMessage
1316
import xyz.flipchat.services.domain.model.chat.ConversationMessageWithMember
1417
import xyz.flipchat.services.domain.model.chat.ConversationMessageWithMemberAndContent
18+
import xyz.flipchat.services.domain.model.chat.ConversationMessageWithMemberAndReplyAndTips
19+
import xyz.flipchat.services.domain.model.chat.MessageTipInfo
1520

1621
@Dao
1722
interface ConversationMessageDao {
@@ -36,7 +41,12 @@ interface ConversationMessageDao {
3641
messages.deletedByBase58 AS deletedByBase58,
3742
messages.content AS content,
3843
members.memberIdBase58 AS memberIdBase58,
39-
members.memberName AS memberName
44+
members.memberName AS memberName,
45+
members.isHost AS isHost,
46+
members.imageUri AS imageUri,
47+
members.isBlocked AS isBlocked,
48+
members.isFullMember AS isFullMember,
49+
members.isMuted AS isMuted
4050
FROM messages
4151
4252
LEFT JOIN members ON messages.senderIdBase58 = members.memberIdBase58
@@ -50,6 +60,39 @@ interface ConversationMessageDao {
5060
return getPagedMessages(id.base58, limit, offset)
5161
}
5262

63+
@Query("SELECT * FROM members WHERE memberIdBase58 = :memberId")
64+
suspend fun getMemberInternal(memberId: String): ConversationMember?
65+
suspend fun getMemberInternal(memberId: ID): ConversationMember? {
66+
return getMemberInternal(memberId.base58)
67+
}
68+
69+
suspend fun getPagedMessagesWithRepliesAndTips(id: ID, limit: Int, offset: Int, selfId: ID?): List<ConversationMessageWithMemberAndReplyAndTips> {
70+
val messages = getPagedMessages(id.base58, limit, offset)
71+
72+
return messages.map {
73+
val content = MessageContent.fromData(it.message.type, it.message.content, isFromSelf = false)
74+
val replyMessage = if (content is MessageContent.Reply) {
75+
getMessageWithContentById(content.originalMessageId, selfId)
76+
} else {
77+
null
78+
}
79+
80+
val tips = getTips(it.message.id, selfId).map { (_, tipperId, amountInQuarks) ->
81+
MessageTipInfo(
82+
kinAmount = KinAmount.fromQuarks(amountInQuarks),
83+
tipper = getMemberInternal(tipperId)
84+
)
85+
}
86+
87+
ConversationMessageWithMemberAndReplyAndTips(
88+
message = it.message,
89+
member = it.member,
90+
reply = replyMessage,
91+
tips = tips
92+
)
93+
}
94+
}
95+
5396
@Query("SELECT COUNT(*) FROM messages WHERE conversationIdBase58 = :conversationId")
5497
suspend fun getTotalMessageCountFor(conversationId: String): Int
5598
suspend fun getTotalMessageCountFor(conversationId: ID): Int {
@@ -140,7 +183,6 @@ interface ConversationMessageDao {
140183
suspend fun markDeleted(messageId: String, by: String)
141184

142185
suspend fun markDeleted(messageId: ID, by: ID) {
143-
println("markdeleted ${messageId.base58} by ${by.base58}")
144186
markDeleted(messageId.base58, by.base58)
145187
}
146188

0 commit comments

Comments
 (0)