mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-12-18 22:52:04 +03:00
WIP temp messages are replaced when same refId received from sever
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
8fbf70ee4e
commit
aff7845e83
10 changed files with 130 additions and 41 deletions
|
@ -2,7 +2,7 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 13,
|
"version": 13,
|
||||||
"identityHash": "6986b68476bae871773348987eada812",
|
"identityHash": "ec1e16b220080592a488165e493b4f89",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "User",
|
"tableName": "User",
|
||||||
|
@ -450,7 +450,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "ChatMessages",
|
"tableName": "ChatMessages",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `id` INTEGER NOT NULL, `internalConversationId` TEXT NOT NULL, `actorDisplayName` TEXT NOT NULL, `message` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `deleted` INTEGER NOT NULL, `expirationTimestamp` INTEGER NOT NULL, `isReplyable` INTEGER NOT NULL, `lastEditActorDisplayName` TEXT, `lastEditActorId` TEXT, `lastEditActorType` TEXT, `lastEditTimestamp` INTEGER, `markdown` INTEGER, `messageParameters` TEXT, `messageType` TEXT NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `referenceId` TEXT, `systemMessage` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `id` INTEGER NOT NULL, `internalConversationId` TEXT NOT NULL, `actorDisplayName` TEXT NOT NULL, `message` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `deleted` INTEGER NOT NULL, `expirationTimestamp` INTEGER NOT NULL, `isReplyable` INTEGER NOT NULL, `lastEditActorDisplayName` TEXT, `lastEditActorId` TEXT, `lastEditActorType` TEXT, `lastEditTimestamp` INTEGER, `markdown` INTEGER, `messageParameters` TEXT, `messageType` TEXT NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `referenceId` TEXT, `systemMessage` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `isTemporary` INTEGER NOT NULL, `sendingFailed` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "internalId",
|
"fieldPath": "internalId",
|
||||||
|
@ -601,6 +601,18 @@
|
||||||
"columnName": "timestamp",
|
"columnName": "timestamp",
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "isTemporary",
|
||||||
|
"columnName": "isTemporary",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sendingFailed",
|
||||||
|
"columnName": "sendingFailed",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
|
@ -725,7 +737,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6986b68476bae871773348987eada812')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ec1e16b220080592a488165e493b4f89')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -441,6 +441,7 @@ class ChatActivity :
|
||||||
chatViewModel = ViewModelProvider(this, viewModelFactory)[ChatViewModel::class.java]
|
chatViewModel = ViewModelProvider(this, viewModelFactory)[ChatViewModel::class.java]
|
||||||
|
|
||||||
messageInputViewModel = ViewModelProvider(this, viewModelFactory)[MessageInputViewModel::class.java]
|
messageInputViewModel = ViewModelProvider(this, viewModelFactory)[MessageInputViewModel::class.java]
|
||||||
|
messageInputViewModel.setData(chatViewModel.getChatRepository())
|
||||||
|
|
||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
delay(DELAY_TO_SHOW_PROGRESS_BAR)
|
delay(DELAY_TO_SHOW_PROGRESS_BAR)
|
||||||
|
@ -914,6 +915,15 @@ class ChatActivity :
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lifecycleScope.launch {
|
||||||
|
chatViewModel.getRemoveMessageFlow
|
||||||
|
.onEach {
|
||||||
|
adapter!!.delete(it)
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
chatViewModel.getUpdateMessageFlow
|
chatViewModel.getUpdateMessageFlow
|
||||||
.onEach {
|
.onEach {
|
||||||
|
|
|
@ -42,6 +42,8 @@ interface ChatMessageRepository : LifecycleAwareManager {
|
||||||
*/
|
*/
|
||||||
val generalUIFlow: Flow<String>
|
val generalUIFlow: Flow<String>
|
||||||
|
|
||||||
|
val removeMessageFlow: Flow<ChatMessage>
|
||||||
|
|
||||||
fun setData(conversationModel: ConversationModel, credentials: String, urlForChatting: String)
|
fun setData(conversationModel: ConversationModel, credentials: String, urlForChatting: String)
|
||||||
|
|
||||||
fun loadInitialMessages(withNetworkParams: Bundle): Job
|
fun loadInitialMessages(withNetworkParams: Bundle): Job
|
||||||
|
|
|
@ -73,8 +73,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
>
|
>
|
||||||
> = MutableSharedFlow()
|
> = MutableSharedFlow()
|
||||||
|
|
||||||
override val updateMessageFlow:
|
override val updateMessageFlow: Flow<ChatMessage>
|
||||||
Flow<ChatMessage>
|
|
||||||
get() = _updateMessageFlow
|
get() = _updateMessageFlow
|
||||||
|
|
||||||
private val _updateMessageFlow:
|
private val _updateMessageFlow:
|
||||||
|
@ -87,8 +86,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
private val _lastCommonReadFlow:
|
private val _lastCommonReadFlow:
|
||||||
MutableSharedFlow<Int> = MutableSharedFlow()
|
MutableSharedFlow<Int> = MutableSharedFlow()
|
||||||
|
|
||||||
override val lastReadMessageFlow:
|
override val lastReadMessageFlow: Flow<Int>
|
||||||
Flow<Int>
|
|
||||||
get() = _lastReadMessageFlow
|
get() = _lastReadMessageFlow
|
||||||
|
|
||||||
private val _lastReadMessageFlow:
|
private val _lastReadMessageFlow:
|
||||||
|
@ -99,6 +97,12 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
|
|
||||||
private val _generalUIFlow: MutableSharedFlow<String> = MutableSharedFlow()
|
private val _generalUIFlow: MutableSharedFlow<String> = MutableSharedFlow()
|
||||||
|
|
||||||
|
override val removeMessageFlow: Flow<ChatMessage>
|
||||||
|
get() = _removeMessageFlow
|
||||||
|
|
||||||
|
private val _removeMessageFlow:
|
||||||
|
MutableSharedFlow<ChatMessage> = MutableSharedFlow()
|
||||||
|
|
||||||
private var newXChatLastCommonRead: Int? = null
|
private var newXChatLastCommonRead: Int? = null
|
||||||
private var itIsPaused = false
|
private var itIsPaused = false
|
||||||
private val scope = CoroutineScope(Dispatchers.IO)
|
private val scope = CoroutineScope(Dispatchers.IO)
|
||||||
|
@ -174,6 +178,9 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
if (newestMessageIdFromDb.toInt() != 0) {
|
if (newestMessageIdFromDb.toInt() != 0) {
|
||||||
val limit = getCappedMessagesAmountOfChatBlock(newestMessageIdFromDb)
|
val limit = getCappedMessagesAmountOfChatBlock(newestMessageIdFromDb)
|
||||||
|
|
||||||
|
// TODO: somewhere here also handle temp messages. updateUiMessages(chatMessages, showUnreadMessagesMarker)
|
||||||
|
|
||||||
|
|
||||||
showMessagesBeforeAndEqual(
|
showMessagesBeforeAndEqual(
|
||||||
internalConversationId,
|
internalConversationId,
|
||||||
newestMessageIdFromDb,
|
newestMessageIdFromDb,
|
||||||
|
@ -295,8 +302,7 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
val weHaveMessagesFromOurself = chatMessages.any { it.actorId == currentUser.userId }
|
val weHaveMessagesFromOurself = chatMessages.any { it.actorId == currentUser.userId }
|
||||||
showUnreadMessagesMarker = showUnreadMessagesMarker && !weHaveMessagesFromOurself
|
showUnreadMessagesMarker = showUnreadMessagesMarker && !weHaveMessagesFromOurself
|
||||||
|
|
||||||
val triple = Triple(true, showUnreadMessagesMarker, chatMessages)
|
updateUiMessages(chatMessages, showUnreadMessagesMarker)
|
||||||
_messageFlow.emit(triple)
|
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "resultsFromSync are null or empty")
|
Log.d(TAG, "resultsFromSync are null or empty")
|
||||||
}
|
}
|
||||||
|
@ -319,6 +325,33 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun updateUiMessages(chatMessages : List<ChatMessage>, showUnreadMessagesMarker: Boolean) {
|
||||||
|
val oldTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
|
||||||
|
.first()
|
||||||
|
.map(ChatMessageEntity::asModel)
|
||||||
|
|
||||||
|
oldTempMessages.forEach { _removeMessageFlow.emit(it) }
|
||||||
|
|
||||||
|
val tripleChatMessages = Triple(true, showUnreadMessagesMarker, chatMessages)
|
||||||
|
_messageFlow.emit(tripleChatMessages)
|
||||||
|
|
||||||
|
|
||||||
|
val chatMessagesReferenceIds = chatMessages.mapTo(HashSet(chatMessages.size)) { it.referenceId }
|
||||||
|
val tempChatMessagesThatCanBeReplaced = oldTempMessages.filter { it.referenceId in chatMessagesReferenceIds }
|
||||||
|
|
||||||
|
chatDao.deleteTempChatMessages(
|
||||||
|
internalConversationId,
|
||||||
|
tempChatMessagesThatCanBeReplaced.map { it.referenceId!! }
|
||||||
|
)
|
||||||
|
|
||||||
|
val remainingTempMessages = chatDao.getTempMessagesForConversation(internalConversationId)
|
||||||
|
.first()
|
||||||
|
.map(ChatMessageEntity::asModel)
|
||||||
|
|
||||||
|
val triple = Triple(true, false, remainingTempMessages)
|
||||||
|
_messageFlow.emit(triple)
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun hasToLoadPreviousMessagesFromServer(beforeMessageId: Long): Boolean {
|
private suspend fun hasToLoadPreviousMessagesFromServer(beforeMessageId: Long): Boolean {
|
||||||
val loadFromServer: Boolean
|
val loadFromServer: Boolean
|
||||||
|
|
||||||
|
@ -797,7 +830,11 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
): Flow<Result<ChatMessage?>> =
|
): Flow<Result<ChatMessage?>> =
|
||||||
flow {
|
flow {
|
||||||
try {
|
try {
|
||||||
val tempChatMessageEntity = createChatMessageEntity(internalConversationId, message.toString())
|
val tempChatMessageEntity = createChatMessageEntity(
|
||||||
|
internalConversationId,
|
||||||
|
message.toString(),
|
||||||
|
referenceId
|
||||||
|
)
|
||||||
// accessing internalConversationId creates UninitializedPropertyException because ChatViewModel and
|
// accessing internalConversationId creates UninitializedPropertyException because ChatViewModel and
|
||||||
// MessageInputViewModel use different instances of ChatRepository for now
|
// MessageInputViewModel use different instances of ChatRepository for now
|
||||||
|
|
||||||
|
@ -819,43 +856,35 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createChatMessageEntity(internalConversationId: String, message: String): ChatMessageEntity {
|
private fun createChatMessageEntity(
|
||||||
// val id = chatMessageCounter++
|
internalConversationId: String,
|
||||||
|
message: String,
|
||||||
|
referenceId: String
|
||||||
|
): ChatMessageEntity {
|
||||||
|
|
||||||
val emoji1 = "\uD83D\uDE00" // 😀
|
val currentTimeMillies = System.currentTimeMillis()
|
||||||
val emoji2 = "\uD83D\uDE1C" // 😜
|
|
||||||
val reactions = LinkedHashMap<String, Int>()
|
|
||||||
reactions[emoji1] = 3
|
|
||||||
reactions[emoji2] = 4
|
|
||||||
|
|
||||||
val reactionsSelf = ArrayList<String>()
|
|
||||||
reactionsSelf.add(emoji1)
|
|
||||||
|
|
||||||
val entity = ChatMessageEntity(
|
val entity = ChatMessageEntity(
|
||||||
internalId = internalConversationId + "_temp1",
|
internalId = internalConversationId + "@_temp_" + currentTimeMillies,
|
||||||
internalConversationId = internalConversationId,
|
internalConversationId = internalConversationId,
|
||||||
id = 111111111,
|
id = currentTimeMillies,
|
||||||
message = message,
|
message = message + " (temp)",
|
||||||
reactions = reactions,
|
|
||||||
reactionsSelf = reactionsSelf,
|
|
||||||
deleted = false,
|
deleted = false,
|
||||||
token = "",
|
token = conversationModel.token,
|
||||||
actorId = "",
|
actorId = currentUser.userId!!,
|
||||||
actorType = "",
|
actorType = "users",
|
||||||
accountId = 1,
|
accountId = currentUser.id!!,
|
||||||
messageParameters = null,
|
messageParameters = null,
|
||||||
messageType = "",
|
messageType = "comment",
|
||||||
parentMessageId = null,
|
parentMessageId = null,
|
||||||
systemMessageType = ChatMessage.SystemMessageType.DUMMY,
|
systemMessageType = ChatMessage.SystemMessageType.DUMMY,
|
||||||
replyable = false,
|
replyable = false,
|
||||||
timestamp = System.currentTimeMillis(),
|
timestamp = System.currentTimeMillis() / MILLIES,
|
||||||
expirationTimestamp = 0,
|
expirationTimestamp = 0,
|
||||||
actorDisplayName = "test",
|
actorDisplayName = currentUser.displayName!!,
|
||||||
lastEditActorType = null,
|
referenceId = referenceId,
|
||||||
lastEditTimestamp = 0L,
|
isTemporary = true,
|
||||||
renderMarkdown = true,
|
sendingFailed = false
|
||||||
lastEditActorId = "",
|
|
||||||
lastEditActorDisplayName = ""
|
|
||||||
)
|
)
|
||||||
return entity
|
return entity
|
||||||
}
|
}
|
||||||
|
@ -868,5 +897,6 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||||
private const val HALF_SECOND = 500L
|
private const val HALF_SECOND = 500L
|
||||||
private const val DELAY_TO_ENSURE_MESSAGES_ARE_ADDED: Long = 100
|
private const val DELAY_TO_ENSURE_MESSAGES_ARE_ADDED: Long = 100
|
||||||
private const val DEFAULT_MESSAGES_LIMIT = 100
|
private const val DEFAULT_MESSAGES_LIMIT = 100
|
||||||
|
private const val MILLIES = 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,10 @@ class ChatViewModel @Inject constructor(
|
||||||
lateinit var currentLifeCycleFlag: LifeCycleFlag
|
lateinit var currentLifeCycleFlag: LifeCycleFlag
|
||||||
val disposableSet = mutableSetOf<Disposable>()
|
val disposableSet = mutableSetOf<Disposable>()
|
||||||
|
|
||||||
|
fun getChatRepository(): ChatMessageRepository {
|
||||||
|
return chatRepository
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
super.onResume(owner)
|
super.onResume(owner)
|
||||||
currentLifeCycleFlag = LifeCycleFlag.RESUMED
|
currentLifeCycleFlag = LifeCycleFlag.RESUMED
|
||||||
|
@ -125,6 +129,8 @@ class ChatViewModel @Inject constructor(
|
||||||
_chatMessageViewState.value = ChatMessageErrorState
|
_chatMessageViewState.value = ChatMessageErrorState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val getRemoveMessageFlow = chatRepository.removeMessageFlow
|
||||||
|
|
||||||
val getUpdateMessageFlow = chatRepository.updateMessageFlow
|
val getUpdateMessageFlow = chatRepository.updateMessageFlow
|
||||||
|
|
||||||
val getLastCommonReadFlow = chatRepository.lastCommonReadFlow
|
val getLastCommonReadFlow = chatRepository.lastCommonReadFlow
|
||||||
|
|
|
@ -34,21 +34,27 @@ import java.lang.Thread.sleep
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MessageInputViewModel @Inject constructor(
|
class MessageInputViewModel @Inject constructor(
|
||||||
private val chatRepository: ChatMessageRepository,
|
|
||||||
private val audioRecorderManager: AudioRecorderManager,
|
private val audioRecorderManager: AudioRecorderManager,
|
||||||
private val mediaPlayerManager: MediaPlayerManager,
|
private val mediaPlayerManager: MediaPlayerManager,
|
||||||
private val audioFocusRequestManager: AudioFocusRequestManager,
|
private val audioFocusRequestManager: AudioFocusRequestManager,
|
||||||
private val appPreferences: AppPreferences
|
private val appPreferences: AppPreferences
|
||||||
) : ViewModel(),
|
) : ViewModel(),
|
||||||
DefaultLifecycleObserver {
|
DefaultLifecycleObserver {
|
||||||
|
|
||||||
enum class LifeCycleFlag {
|
enum class LifeCycleFlag {
|
||||||
PAUSED,
|
PAUSED,
|
||||||
RESUMED,
|
RESUMED,
|
||||||
STOPPED
|
STOPPED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lateinit var chatRepository: ChatMessageRepository
|
||||||
lateinit var currentLifeCycleFlag: LifeCycleFlag
|
lateinit var currentLifeCycleFlag: LifeCycleFlag
|
||||||
val disposableSet = mutableSetOf<Disposable>()
|
val disposableSet = mutableSetOf<Disposable>()
|
||||||
|
|
||||||
|
fun setData(chatMessageRepository: ChatMessageRepository){
|
||||||
|
chatRepository = chatMessageRepository
|
||||||
|
}
|
||||||
|
|
||||||
data class QueuedMessage(
|
data class QueuedMessage(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
var message: CharSequence? = null,
|
var message: CharSequence? = null,
|
||||||
|
|
|
@ -152,7 +152,6 @@ class RepositoryModule {
|
||||||
@Provides
|
@Provides
|
||||||
fun provideInvitationsRepository(ncApi: NcApi): InvitationsRepository = InvitationsRepositoryImpl(ncApi)
|
fun provideInvitationsRepository(ncApi: NcApi): InvitationsRepository = InvitationsRepositoryImpl(ncApi)
|
||||||
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideOfflineFirstChatRepository(
|
fun provideOfflineFirstChatRepository(
|
||||||
chatMessagesDao: ChatMessagesDao,
|
chatMessagesDao: ChatMessagesDao,
|
||||||
|
|
|
@ -22,6 +22,7 @@ interface ChatMessagesDao {
|
||||||
SELECT MAX(id) as max_items
|
SELECT MAX(id) as max_items
|
||||||
FROM ChatMessages
|
FROM ChatMessages
|
||||||
WHERE internalConversationId = :internalConversationId
|
WHERE internalConversationId = :internalConversationId
|
||||||
|
AND isTemporary = 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
fun getNewestMessageId(internalConversationId: String): Long
|
fun getNewestMessageId(internalConversationId: String): Long
|
||||||
|
@ -36,6 +37,17 @@ interface ChatMessagesDao {
|
||||||
)
|
)
|
||||||
fun getMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
fun getMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
SELECT *
|
||||||
|
FROM ChatMessages
|
||||||
|
WHERE internalConversationId = :internalConversationId
|
||||||
|
AND isTemporary = 1
|
||||||
|
ORDER BY timestamp DESC, id DESC
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>)
|
suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>)
|
||||||
|
|
||||||
|
@ -59,6 +71,16 @@ interface ChatMessagesDao {
|
||||||
)
|
)
|
||||||
fun deleteChatMessages(messageIds: List<Int>)
|
fun deleteChatMessages(messageIds: List<Int>)
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
value = """
|
||||||
|
DELETE FROM ChatMessages
|
||||||
|
WHERE internalConversationId = :internalConversationId
|
||||||
|
AND referenceId in (:referenceIds)
|
||||||
|
AND isTemporary = 1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun deleteTempChatMessages(internalConversationId: String, referenceIds: List<String>)
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
fun updateChatMessage(message: ChatMessageEntity)
|
fun updateChatMessage(message: ChatMessageEntity)
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ data class ChatMessageEntity(
|
||||||
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
||||||
@ColumnInfo(name = "referenceId") var referenceId: String? = null,
|
@ColumnInfo(name = "referenceId") var referenceId: String? = null,
|
||||||
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
||||||
@ColumnInfo(name = "timestamp") var timestamp: Long = 0
|
@ColumnInfo(name = "timestamp") var timestamp: Long = 0,
|
||||||
|
@ColumnInfo(name = "isTemporary") var isTemporary: Boolean = false,
|
||||||
|
@ColumnInfo(name = "sendingFailed") var sendingFailed: Boolean = false,
|
||||||
// missing/not needed: silent
|
// missing/not needed: silent
|
||||||
)
|
)
|
||||||
|
|
|
@ -108,7 +108,7 @@ abstract class TalkDatabase : RoomDatabase() {
|
||||||
return Room
|
return Room
|
||||||
.databaseBuilder(context.applicationContext, TalkDatabase::class.java, dbName)
|
.databaseBuilder(context.applicationContext, TalkDatabase::class.java, dbName)
|
||||||
// comment out openHelperFactory to view the database entries in Android Studio for debugging
|
// comment out openHelperFactory to view the database entries in Android Studio for debugging
|
||||||
.openHelperFactory(factory)
|
// .openHelperFactory(factory)
|
||||||
.addMigrations(
|
.addMigrations(
|
||||||
Migrations.MIGRATION_6_8,
|
Migrations.MIGRATION_6_8,
|
||||||
Migrations.MIGRATION_7_8,
|
Migrations.MIGRATION_7_8,
|
||||||
|
|
Loading…
Reference in a new issue