Skip to content

Commit 68e26e7

Browse files
committed
chore: add missing verified state handling for sorting
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 095df45 commit 68e26e7

File tree

11 files changed

+164
-139
lines changed

11 files changed

+164
-139
lines changed

libs/models/src/main/kotlin/com/getcode/model/chat/Sender.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ data class LinkedSocialProfile(
7575
val platformType: String,
7676
val username: String,
7777
val profileImageUrl: String?,
78+
val isVerifiedOnPlatform: Boolean,
7879
val rawMetadata: String?,
7980
) {
8081
inline fun <reified M> metadata(): M? = runCatching {

libs/models/src/main/kotlin/com/getcode/model/social/user/SocialProfile.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ sealed interface SocialProfile {
6969
platformType = "x",
7070
username = username,
7171
profileImageUrl = profilePicUrl,
72+
isVerifiedOnPlatform = verificationType != X.VerificationType.NONE,
7273
rawMetadata = Json.encodeToString(metadata)
7374
)
7475
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,8 @@ data class ConversationWithMembersAndLastMessage(
119119

120120
val messageContentPreview: MessageContent?
121121
get() = lastMessage?.let { MessageContent.fromData(it.type, it.content, false) }
122+
123+
@Ignore
124+
var pageIndex: Int? = null
122125
}
123126

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ fun MemberSocialProfile.toLinked(): LinkedSocialProfile? {
2525
platformType = platformType,
2626
username = username,
2727
profileImageUrl = profileImageUrl,
28+
isVerifiedOnPlatform = verified,
2829
rawMetadata = extraData
2930
)
3031
}

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,6 @@ interface ConversationMessageDao {
346346
tipperIdBase58 = tipContent.tipperId.base58
347347
)
348348

349-
incrementTipCount(tipContent.originalMessageId)
350-
351349
addTip(tip)
352350
}
353351

@@ -362,8 +360,6 @@ interface ConversationMessageDao {
362360
emoji = reactionContent.emoji,
363361
)
364362

365-
incrementReactionCount(reactionContent.originalMessageId)
366-
367363
addReaction(reaction)
368364
}
369365

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ interface MemberSocialProfileDao {
4949
username = profile.username,
5050
profileImageUrl = profile.profilePicUrl,
5151
platformType = "x",
52+
verified = profile.verificationType != SocialProfile.X.VerificationType.NONE,
5253
extraData = Json.encodeToString(metadata)
5354
)
5455
}

services/flipchat/sdk/src/main/kotlin/xyz/flipchat/chat/RoomController.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,11 @@ class RoomController @Inject constructor(
215215
userId = { userManager.userId }
216216
)
217217
) {
218-
MessagingPagingSource(conversationId, { userManager.userId }, db)
218+
MessagingPagingSource(
219+
chatId = conversationId,
220+
userId = { userManager.userId },
221+
db = db,
222+
)
219223
}
220224

221225
fun observeTyping(conversationId: ID) = messagingRepository.observeTyping(conversationId)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package xyz.flipchat.chat.paging
2+
3+
import android.annotation.SuppressLint
4+
import androidx.paging.PagingSource
5+
import androidx.paging.PagingState
6+
import androidx.room.paging.util.ThreadSafeInvalidationObserver
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.withContext
9+
import xyz.flipchat.internal.db.FcAppDatabase
10+
import xyz.flipchat.services.domain.model.chat.ConversationWithMembersAndLastMessage
11+
12+
internal class ChatsPagingSource(
13+
private val db: FcAppDatabase
14+
) : PagingSource<Int, ConversationWithMembersAndLastMessage>() {
15+
16+
@SuppressLint("RestrictedApi")
17+
private val observer =
18+
ThreadSafeInvalidationObserver(arrayOf("conversations", "messages", "members")) {
19+
invalidate()
20+
}
21+
22+
override fun getRefreshKey(state: PagingState<Int, ConversationWithMembersAndLastMessage>): Int? {
23+
val anchorPos = state.anchorPosition ?: return null
24+
val anchorItem = state.closestItemToPosition(anchorPos) ?: return null
25+
// The anchor item *knows* which page it was loaded from:
26+
return anchorItem.pageIndex
27+
}
28+
29+
@SuppressLint("RestrictedApi")
30+
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ConversationWithMembersAndLastMessage> {
31+
observer.registerIfNecessary(db)
32+
val currentPage = params.key ?: 0
33+
val pageSize = params.loadSize
34+
val offset = currentPage * pageSize
35+
36+
return withContext(Dispatchers.IO) {
37+
try {
38+
val conversations = db.conversationDao().getPagedConversations(pageSize, offset)
39+
.map { it.apply { pageIndex = currentPage } }
40+
41+
val prevKey = null
42+
val nextKey = if (conversations.size < pageSize) null else currentPage + 1
43+
44+
45+
LoadResult.Page(conversations, prevKey, nextKey)
46+
} catch (e: Exception) {
47+
LoadResult.Error(e)
48+
}
49+
}
50+
}
51+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package xyz.flipchat.chat.paging
2+
3+
import androidx.paging.ExperimentalPagingApi
4+
import androidx.paging.LoadType
5+
import androidx.paging.PagingState
6+
import androidx.paging.RemoteMediator
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.withContext
9+
import xyz.flipchat.internal.db.FcAppDatabase
10+
import xyz.flipchat.services.data.Room
11+
import xyz.flipchat.services.domain.mapper.RoomConversationMapper
12+
import xyz.flipchat.services.domain.model.chat.ConversationWithMembersAndLastMessage
13+
import xyz.flipchat.services.domain.model.query.QueryOptions
14+
import xyz.flipchat.services.internal.network.repository.chat.ChatRepository
15+
16+
@OptIn(ExperimentalPagingApi::class)
17+
internal class ChatsRemoteMediator(
18+
private val repository: ChatRepository,
19+
private val conversationMapper: RoomConversationMapper,
20+
) : RemoteMediator<Int, ConversationWithMembersAndLastMessage>() {
21+
22+
private val db = FcAppDatabase.requireInstance()
23+
24+
override suspend fun initialize(): InitializeAction {
25+
return InitializeAction.SKIP_INITIAL_REFRESH
26+
}
27+
28+
private var lastResult = listOf<Room>()
29+
30+
override suspend fun load(
31+
loadType: LoadType,
32+
state: PagingState<Int, ConversationWithMembersAndLastMessage>
33+
): MediatorResult {
34+
return try {
35+
val loadKey = when (loadType) {
36+
LoadType.REFRESH -> {
37+
null
38+
}
39+
40+
LoadType.PREPEND -> {
41+
return MediatorResult.Success(true) // Don't load newer messages
42+
}
43+
44+
LoadType.APPEND -> {
45+
// Get the last item from our data
46+
val lastItem = state.lastItemOrNull()
47+
?: return MediatorResult.Success(
48+
// If we don't have any items, only signal end of pagination
49+
// if we've had a refresh
50+
endOfPaginationReached = state.pages.isNotEmpty()
51+
)
52+
53+
lastItem.conversation.id
54+
}
55+
}
56+
57+
val limit = state.config.pageSize
58+
59+
val query = QueryOptions(
60+
limit = limit,
61+
token = loadKey,
62+
descending = true
63+
)
64+
65+
val response = repository.getChats(query)
66+
val rooms = response.getOrNull().orEmpty()
67+
68+
if (rooms.isEmpty() || lastResult.any { it.id == rooms.firstOrNull()?.id.orEmpty() }) {
69+
lastResult = emptyList()
70+
return MediatorResult.Success(true)
71+
}
72+
73+
lastResult = rooms
74+
75+
// Map the rooms to your Room entities
76+
val conversations = rooms.map { conversationMapper.map(it) }
77+
78+
// Update the database with the new data (upsert)
79+
withContext(Dispatchers.IO) {
80+
if (loadType == LoadType.REFRESH) {
81+
// Clear all conversations before loading the fresh data
82+
db.conversationDao().clearConversations()
83+
}
84+
85+
// Insert or update the conversations
86+
db.conversationDao().upsertConversations(*conversations.toTypedArray())
87+
}
88+
89+
MediatorResult.Success(endOfPaginationReached = rooms.size < limit)
90+
} catch (e: Exception) {
91+
MediatorResult.Error(e)
92+
}
93+
}
94+
}

services/flipchat/sdk/src/main/kotlin/xyz/flipchat/chat/paging/MessagingPagingSource.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import androidx.paging.PagingState
66
import androidx.room.paging.util.ThreadSafeInvalidationObserver
77
import com.getcode.model.ID
88
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.runBlocking
910
import kotlinx.coroutines.withContext
1011
import xyz.flipchat.internal.db.FcAppDatabase
1112
import xyz.flipchat.services.domain.model.chat.InflatedConversationMessage
1213

1314
internal class MessagingPagingSource(
1415
private val chatId: ID,
1516
private val userId: () -> ID?,
16-
private val db: FcAppDatabase
17+
private val db: FcAppDatabase,
1718
) : PagingSource<Int, InflatedConversationMessage>() {
1819

1920
@SuppressLint("RestrictedApi")
@@ -38,15 +39,15 @@ internal class MessagingPagingSource(
3839

3940
return withContext(Dispatchers.Default) {
4041
try {
41-
val messages =
42-
db.conversationMessageDao()
42+
val messages = db.conversationMessageDao()
4343
.getPagedMessagesWithDetails(chatId, pageSize, offset, userId())
44+
.map { it.copy(pageIndex = currentPage) }
4445

4546
val prevKey = if (currentPage > 0 && messages.isNotEmpty()) currentPage - 1 else null
4647
val nextKey = if (messages.size < pageSize) null else currentPage + 1
4748

4849
LoadResult.Page(
49-
data = messages.map { if (prevKey == null) it.copy(pageIndex = currentPage) else it },
50+
data = messages,
5051
prevKey = prevKey,
5152
nextKey = nextKey,
5253
)

0 commit comments

Comments
 (0)