Skip to content

Commit 4fe30d0

Browse files
committed
feat: support mixed pointers for chat message statuses
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent e1179bd commit 4fe30d0

41 files changed

Lines changed: 1232 additions & 169 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/schemas/com.getcode.db.AppDatabase/14.json

Lines changed: 421 additions & 0 deletions
Large diffs are not rendered by default.

api/src/main/java/com/getcode/db/AppDatabase.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import java.io.File
3535
GiftCard::class,
3636
ExchangeRate::class,
3737
Conversation::class,
38+
ConversationPointerCrossRef::class,
3839
ConversationMessage::class,
3940
ConversationIntentIdReference::class,
4041
ConversationMessageContent::class,
@@ -45,8 +46,9 @@ import java.io.File
4546
AutoMigration(from = 10, to = 11, spec = AppDatabase.Migration10To11::class),
4647
AutoMigration(from = 11, to = 12, spec = AppDatabase.Migration11To12::class),
4748
AutoMigration(from = 12, to = 13, spec = AppDatabase.Migration12To13::class),
49+
AutoMigration(from = 13, to = 14, spec = AppDatabase.Migration13To14::class),
4850
],
49-
version = 13
51+
version = 14
5052
)
5153
@TypeConverters(Converters::class)
5254
abstract class AppDatabase : RoomDatabase() {
@@ -58,6 +60,7 @@ abstract class AppDatabase : RoomDatabase() {
5860
abstract fun exchangeDao(): ExchangeDao
5961

6062
abstract fun conversationDao(): ConversationDao
63+
abstract fun conversationPointersDao(): ConversationPointerDao
6164
abstract fun conversationMessageDao(): ConversationMessageDao
6265
abstract fun conversationIntentMappingDao(): ConversationIntentMappingDao
6366

@@ -112,6 +115,14 @@ abstract class AppDatabase : RoomDatabase() {
112115
db.execSQL("DROP TABLE messages")
113116
}
114117
}
118+
119+
@DeleteColumn.Entries(
120+
DeleteColumn(
121+
tableName = "messages",
122+
columnName = "status"
123+
)
124+
)
125+
class Migration13To14: AutoMigrationSpec
115126
}
116127

117128
object Database {
@@ -133,7 +144,7 @@ object Database {
133144

134145
instance =
135146
Room.databaseBuilder(context, AppDatabase::class.java, dbName)
136-
.openHelperFactory(SupportFactory(entropyB64.decodeBase64(), null, false))
147+
// .openHelperFactory(SupportFactory(entropyB64.decodeBase64(), null, false))
137148
.fallbackToDestructiveMigration()
138149
.build()
139150

api/src/main/java/com/getcode/db/ConversationDao.kt

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package com.getcode.db
22

33
import androidx.room.Dao
4+
import androidx.room.Delete
45
import androidx.room.Insert
56
import androidx.room.OnConflictStrategy
67
import androidx.room.Query
8+
import androidx.room.RewriteQueriesToDropUnusedColumns
9+
import androidx.room.Transaction
710
import com.getcode.model.Conversation
11+
import com.getcode.model.ConversationWithLastPointers
812
import com.getcode.model.ID
913
import com.getcode.network.repository.base58
1014
import kotlinx.coroutines.flow.Flow
@@ -15,17 +19,19 @@ interface ConversationDao {
1519
@Insert(onConflict = OnConflictStrategy.REPLACE)
1620
suspend fun upsertConversations(vararg conversation: Conversation)
1721

18-
@Query("SELECT * FROM conversations WHERE idBase58 = :id")
19-
fun observeConversation(id: String): Flow<Conversation?>
22+
@RewriteQueriesToDropUnusedColumns
23+
@Query("SELECT * FROM conversations LEFT JOIN conversation_pointers ON conversations.idBase58 = conversation_pointers.conversationIdBase58 WHERE conversations.idBase58 = :id")
24+
fun observeConversation(id: String): Flow<ConversationWithLastPointers?>
2025

21-
fun observeConversation(id: ID): Flow<Conversation?> {
26+
fun observeConversation(id: ID): Flow<ConversationWithLastPointers?> {
2227
return observeConversation(id.base58)
2328
}
2429

25-
@Query("SELECT * FROM conversations WHERE idBase58 = :id")
26-
suspend fun findConversation(id: String): Conversation?
30+
@RewriteQueriesToDropUnusedColumns
31+
@Query("SELECT * FROM conversations LEFT JOIN conversation_pointers ON conversations.idBase58 = conversation_pointers.conversationIdBase58 WHERE conversations.idBase58 = :id")
32+
suspend fun findConversation(id: String): ConversationWithLastPointers?
2733

28-
suspend fun findConversation(id: ID): Conversation? {
34+
suspend fun findConversation(id: ID): ConversationWithLastPointers? {
2935
return findConversation(id.base58)
3036
}
3137

@@ -46,6 +52,22 @@ interface ConversationDao {
4652
// return hasRevealedIdentity(messageId.base58)
4753
// }
4854

55+
@Delete
56+
fun deleteConversation(conversation: Conversation)
57+
58+
@Query("DELETE FROM conversations WHERE idBase58 = :id")
59+
suspend fun deleteConversationById(id: String)
60+
61+
suspend fun deleteConversationById(id: ID) {
62+
deleteConversationById(id.base58)
63+
}
64+
65+
@Query("DELETE FROM conversations WHERE idBase58 NOT IN (:chatIds)")
66+
suspend fun purgeConversationsNotInByString(chatIds: List<String>)
67+
suspend fun purgeConversationsNotIn(chatIds: List<ID>) {
68+
purgeConversationsNotInByString(chatIds.map { it.base58 })
69+
}
70+
4971
@Query("DELETE FROM conversations")
5072
fun clearConversations()
5173
}

api/src/main/java/com/getcode/db/ConversationIntentMappingDao.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ interface ConversationIntentMappingDao {
2020
return conversationIdByReference(id.base58)
2121
}
2222

23+
@Query("DELETE FROM conversation_intent_id_mapping WHERE conversationIdBase58 NOT IN (:chatIds)")
24+
suspend fun purgeMappingNoLongerNeededByString(chatIds: List<String>)
25+
26+
suspend fun purgeMappingNoLongerNeeded(chatIds: List<ID>) {
27+
purgeMappingNoLongerNeededByString(chatIds.map { it.base58 })
28+
}
29+
2330
@Query("DELETE FROM conversation_intent_id_mapping")
2431
suspend fun clearMapping()
2532
}

api/src/main/java/com/getcode/db/ConversationMessageDao.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.room.Dao
55
import androidx.room.Insert
66
import androidx.room.OnConflictStrategy
77
import androidx.room.Query
8+
import androidx.room.RewriteQueriesToDropUnusedColumns
89
import androidx.room.Transaction
910
import com.getcode.model.ConversationMessage
1011
import com.getcode.model.ConversationMessageContent
@@ -49,8 +50,9 @@ interface ConversationMessageDao {
4950
}
5051
}
5152

53+
@RewriteQueriesToDropUnusedColumns
5254
@Transaction
53-
@Query("SELECT * FROM messages JOIN message_contents ON messages.idBase58 = message_contents.messageIdBase58 WHERE conversationIdBase58 = :id ORDER BY dateMillis DESC")
55+
@Query("SELECT * FROM messages JOIN message_contents ON messages.idBase58 = message_contents.messageIdBase58 WHERE conversationIdBase58 = :id ORDER BY dateMillis DESC")
5456
fun observeConversationMessages(id: String): PagingSource<Int, ConversationMessageWithContent>
5557

5658
fun observeConversationMessages(id: ID): PagingSource<Int, ConversationMessageWithContent> {
@@ -64,6 +66,27 @@ interface ConversationMessageDao {
6466
return queryMessages(conversationId.base58)
6567
}
6668

69+
@Query("SELECT * FROM messages WHERE conversationIdBase58 = :conversationId ORDER BY dateMillis DESC LIMIT 1")
70+
suspend fun getNewestMessage(conversationId: String): ConversationMessage?
71+
72+
suspend fun getNewestMessage(conversationId: ID): ConversationMessage? {
73+
return getNewestMessage(conversationId.base58)
74+
}
75+
76+
@Query("DELETE FROM messages WHERE conversationIdBase58 = :conversationId")
77+
suspend fun deleteForConversation(conversationId: String)
78+
79+
suspend fun deleteForConversation(conversationId: ID) {
80+
deleteForConversation(conversationId.base58)
81+
}
82+
83+
@Query("DELETE FROM messages WHERE conversationIdBase58 NOT IN (:chatIds)")
84+
suspend fun purgeMessagesNotInByString(chatIds: List<String>)
85+
86+
suspend fun purgeMessagesNotIn(chatIds: List<ID>) {
87+
purgeMessagesNotInByString(chatIds.map { it.base58 })
88+
}
89+
6790
@Query("DELETE FROM messages")
6891
fun clearMessages()
6992
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.getcode.db
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.OnConflictStrategy
6+
import androidx.room.Query
7+
import androidx.room.Transaction
8+
import com.getcode.model.Conversation
9+
import com.getcode.model.ConversationIntentIdReference
10+
import com.getcode.model.ConversationPointerCrossRef
11+
import com.getcode.model.ID
12+
import com.getcode.model.MessageStatus
13+
import com.getcode.network.repository.base58
14+
import java.util.UUID
15+
16+
@Dao
17+
interface ConversationPointerDao {
18+
@Insert(onConflict = OnConflictStrategy.REPLACE)
19+
suspend fun insert(crossRef: ConversationPointerCrossRef)
20+
21+
suspend fun insert(conversationId: ID, messageId: UUID, status: MessageStatus) {
22+
insert(ConversationPointerCrossRef(conversationId.base58, messageId.toString(), status))
23+
}
24+
25+
@Query("SELECT * FROM conversation_pointers")
26+
suspend fun queryPointers(): List<ConversationPointerCrossRef>
27+
28+
@Query("DELETE FROM conversation_pointers WHERE conversationIdBase58 = :id")
29+
suspend fun deletePointerForConversation(id: String)
30+
31+
suspend fun deletePointerForConversation(id: ID) {
32+
deletePointerForConversation(id.base58)
33+
}
34+
35+
@Query("DELETE FROM conversation_pointers WHERE conversationIdBase58 NOT IN (:chatIds)")
36+
suspend fun purgePointersNoLongerNeededByString(chatIds: List<String>)
37+
38+
suspend fun purgePointersNoLongerNeeded(chatIds: List<ID>) {
39+
purgePointersNoLongerNeededByString(chatIds.map { it.base58 })
40+
}
41+
42+
@Query("DELETE FROM conversation_pointers")
43+
suspend fun clearMapping()
44+
}

api/src/main/java/com/getcode/mapper/ChatMessageV1Mapper.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ class ChatMessageV1Mapper @Inject constructor(
2121

2222
return ChatMessage(
2323
id = messageId,
24-
senderId = emptyList(),
24+
senderId = null,
2525
isFromSelf = isFromSelf,
2626
cursor = message.cursor.value.toList(),
2727
dateMillis = message.ts.seconds * 1_000L,
2828
contents = contents,
29-
status = if (isFromSelf) MessageStatus.Sent else MessageStatus.Incoming
29+
// status = if (isFromSelf) MessageStatus.Sent else MessageStatus.Incoming
3030
)
3131
}
3232
}
Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.getcode.mapper
22

33

4-
import com.getcode.model.MessageStatus
54
import com.getcode.model.chat.Chat
65
import com.getcode.model.chat.ChatMessage
76
import com.getcode.model.chat.MessageContent
8-
import com.getcode.model.chat.Pointer
97
import com.getcode.model.uuid
108
import javax.inject.Inject
119
import com.codeinc.gen.chat.v2.ChatService.ChatMessage as ApiChatMessage
@@ -18,11 +16,9 @@ class ChatMessageV2Mapper @Inject constructor(
1816
val (chat, message) = from
1917

2018
val messageId = message.messageId.value.toByteArray().toList()
21-
val messageSenderId = message.senderId.value.toByteArray().toList()
19+
val messageSenderId = message.senderId.value.toByteArray().toList().uuid
2220
val selfMember = chat.members.firstOrNull { it.isSelf }
23-
val isFromSelf = selfMember?.id == messageSenderId.uuid
24-
val pointers = chat.members.firstOrNull { it.id == messageSenderId.uuid }?.pointers
25-
val messagePointer = pointers?.find { it.id == messageId }
21+
val isFromSelf = selfMember?.id == messageSenderId
2622

2723
return ChatMessage(
2824
id = messageId,
@@ -31,19 +27,6 @@ class ChatMessageV2Mapper @Inject constructor(
3127
cursor = message.cursor.value.toList(),
3228
dateMillis = message.ts.seconds * 1_000L,
3329
contents = message.contentList.mapNotNull { MessageContent(it, isFromSelf) },
34-
status = when (messagePointer) {
35-
is Pointer.Delivered -> MessageStatus.Delivered
36-
is Pointer.Read -> MessageStatus.Read
37-
is Pointer.Sent -> MessageStatus.Sent
38-
// SENT pointers should be inferred by persistence on server.
39-
else -> {
40-
if (isFromSelf) {
41-
MessageStatus.Sent
42-
} else {
43-
MessageStatus.Unknown
44-
}
45-
}
46-
}
4730
)
4831
}
4932
}

api/src/main/java/com/getcode/mapper/ConversationMapper.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
package com.getcode.mapper
22

33
import com.getcode.model.Conversation
4-
import com.getcode.model.KinAmount
5-
import com.getcode.model.Rate
64
import com.getcode.model.chat.Chat
7-
import com.getcode.model.chat.ChatMessage
8-
import com.getcode.model.chat.MessageContent
9-
import com.getcode.model.orOneToOne
10-
import com.getcode.network.exchange.Exchange
115
import com.getcode.network.localized
126
import com.getcode.network.repository.base58
137
import com.getcode.util.resources.ResourceHelper

api/src/main/java/com/getcode/mapper/ConversationMessageMapper.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import javax.inject.Inject
99
class ConversationMessageMapper @Inject constructor() :
1010
Mapper<Pair<ID, ChatMessage>, ConversationMessage> {
1111
override fun map(from: Pair<ID, ChatMessage>): ConversationMessage {
12-
val (conversation, message) = from
12+
val (conversationId, message) = from
1313

1414
return ConversationMessage(
1515
idBase58 = message.id.base58,
1616
cursorBase58 = message.cursor.base58,
17-
conversationIdBase58 = conversation.base58,
17+
conversationIdBase58 = conversationId.base58,
1818
dateMillis = message.dateMillis,
19-
status = message.status
19+
// status = message.status
2020
)
2121
}
2222
}

0 commit comments

Comments
 (0)