add fields for message threads to DB etc.

(cascade delete in migration fails for now)

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2025-06-25 11:41:45 +02:00
parent c468ba4df6
commit 28963c5080
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
11 changed files with 82 additions and 16 deletions

View File

@ -45,6 +45,10 @@ data class ChatMessage(
var token: String? = null,
var topmostParentId: Long? = null,
var childrenCount: Long? = 0,
// guests or users
var actorType: String? = null,

View File

@ -122,11 +122,16 @@ class OfflineFirstChatRepository @Inject constructor(
private var threadId: Long? = null
override fun initData(credentials: String, urlForChatting: String, roomToken: String, threadId: Long?) {
internalConversationId = currentUser.id.toString() + "@" + roomToken
val threadIdAppendedString = if (threadId != null && threadId > 0) {
"@$threadId"
} else {
""
}
internalConversationId = currentUser.id.toString() + "@" + roomToken + threadIdAppendedString
this.credentials = credentials
this.urlForChatting = urlForChatting
this.threadId = threadId // TODO: use this threadId in API requests when fetching messages? +
// TODO Introduce ChatBlocks for threads
this.threadId = threadId // use this threadId in API requests when fetching messages? +
// Introduce ChatBlocks for threads
}
override fun updateConversation(conversationModel: ConversationModel) {
@ -764,6 +769,7 @@ class OfflineFirstChatRepository @Inject constructor(
internalConversationId = internalConversationId,
accountId = conversationModel.accountId,
token = conversationModel.token,
threadId = conversationModel.threadId,
oldestMessageId = oldestIdFromDbChatBlocks,
newestMessageId = newestIdFromDbChatBlocks,
hasHistory = hasHistory

View File

@ -19,6 +19,8 @@ fun ChatMessageJson.asEntity(accountId: Long) =
accountId = accountId,
id = id,
internalConversationId = "$accountId@$token",
topmostParentId = topmostParentId,
childrenCount = childrenCount,
message = message!!,
token = token!!,
actorType = actorType!!,
@ -48,6 +50,8 @@ fun ChatMessageEntity.asModel() =
jsonMessageId = id.toInt(),
message = message,
token = token,
topmostParentId = topmostParentId,
childrenCount = childrenCount,
actorType = actorType,
actorId = actorId,
actorDisplayName = actorDisplayName,
@ -78,6 +82,8 @@ fun ChatMessageJson.asModel() =
jsonMessageId = id.toInt(),
message = message,
token = token,
topmostParentId = topmostParentId,
childrenCount = childrenCount,
actorType = actorType,
actorId = actorId,
actorDisplayName = actorDisplayName,

View File

@ -31,10 +31,11 @@ import androidx.room.PrimaryKey
data class ChatBlockEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id") var id: Long = 0,
// accountId@token
// accountId@token(@threadId)
@ColumnInfo(name = "internalConversationId") var internalConversationId: String,
@ColumnInfo(name = "accountId") var accountId: Long? = null,
@ColumnInfo(name = "token") var token: String?,
@ColumnInfo(name = "threadId") var threadId: Long? = null,
@ColumnInfo(name = "oldestMessageId") var oldestMessageId: Long,
@ColumnInfo(name = "newestMessageId") var newestMessageId: Long,
@ColumnInfo(name = "hasHistory") var hasHistory: Boolean

View File

@ -41,7 +41,7 @@ data class ChatMessageEntity(
@ColumnInfo(name = "id") var id: Long = 0,
// accountId@roomtoken
@ColumnInfo(name = "internalConversationId") var internalConversationId: String,
@ColumnInfo(name = "topmostParentId") var topmostParentId: Long? = null,
@ColumnInfo(name = "actorDisplayName") var actorDisplayName: String,
@ColumnInfo(name = "message") var message: String,
@ -49,6 +49,7 @@ data class ChatMessageEntity(
@ColumnInfo(name = "actorId") var actorId: String,
@ColumnInfo(name = "actorType") var actorType: String,
@ColumnInfo(name = "childrenCount") var childrenCount: Long? = 0,
@ColumnInfo(name = "deleted") var deleted: Boolean = false,
@ColumnInfo(name = "expirationTimestamp") var expirationTimestamp: Int = 0,
@ColumnInfo(name = "isReplyable") var replyable: Boolean = false,

View File

@ -49,6 +49,8 @@ data class ConversationEntity(
// exactly what we want for this case.
@ColumnInfo(name = "token") var token: String,
@ColumnInfo(name = "threadId") var threadId: Long? = null,
@ColumnInfo(name = "displayName") var displayName: String,
// OTHER ATTRIBUTES IN ALPHABETICAL ORDER

View File

@ -89,6 +89,13 @@ object Migrations {
}
}
val MIGRATION_17_18 = object : Migration(17, 18) {
override fun migrate(db: SupportSQLiteDatabase) {
Log.i("Migrations", "Migrating 17 to 18")
migrateToMessageThreads(db)
}
}
//endregion
fun migrateToRoom(db: SupportSQLiteDatabase) {
@ -297,7 +304,7 @@ object Migrations {
"ADD COLUMN hasArchived INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "hasArchived already exists")
Log.i("Migrations", "hasArchived already exists", e)
}
}
@ -308,7 +315,7 @@ object Migrations {
"ADD COLUMN objectId TEXT NOT NULL DEFAULT '';"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column objectId to table Conversations")
Log.i("Migrations", "Something went wrong when adding column objectId to table Conversations", e)
}
}
@ -319,7 +326,7 @@ object Migrations {
"ADD COLUMN hasSensitive INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column hasSensitive to table Conversations")
Log.i("Migrations", "Something went wrong when adding column hasSensitive to table Conversations", e)
}
}
@ -330,7 +337,39 @@ object Migrations {
"ADD COLUMN hasImportant INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column hasImportant to table Conversations")
Log.i("Migrations", "Something went wrong when adding column hasImportant to table Conversations", e)
}
}
fun migrateToMessageThreads(db: SupportSQLiteDatabase) {
try {
// db.execSQL("PRAGMA foreign_keys=ON;")
db.execSQL(
"ALTER TABLE ChatBlocks " +
"ADD COLUMN threadId INTEGER DEFAULT NULL;"
)
db.execSQL(
"ALTER TABLE ChatMessages " +
"ADD COLUMN topmostParentId INTEGER DEFAULT NULL;"
)
db.execSQL(
"ALTER TABLE ChatMessages " +
"ADD COLUMN childrenCount INTEGER DEFAULT 0;"
)
db.execSQL(
"ALTER TABLE Conversations " +
"ADD COLUMN threadId INTEGER DEFAULT NULL;"
)
db.execSQL(
"DELETE FROM Conversations"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when migrating to messageThreads", e)
}
}
@ -341,7 +380,7 @@ object Migrations {
"ADD COLUMN referenceId TEXT;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column referenceId to table ChatMessages")
Log.i("Migrations", "Something went wrong when adding column referenceId to table ChatMessages", e)
}
try {
@ -350,7 +389,7 @@ object Migrations {
"ADD COLUMN isTemporary INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column isTemporary to table ChatMessages")
Log.i("Migrations", "Something went wrong when adding column isTemporary to table ChatMessages", e)
}
try {
@ -359,7 +398,7 @@ object Migrations {
"ADD COLUMN sendingFailed INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column sendingFailed to table ChatMessages")
Log.i("Migrations", "Something went wrong when adding column sendingFailed to table ChatMessages", e)
}
try {
@ -368,7 +407,7 @@ object Migrations {
"ADD COLUMN silent INTEGER NOT NULL DEFAULT 0;"
)
} catch (e: SQLException) {
Log.i("Migrations", "Something went wrong when adding column silent to table ChatMessages")
Log.i("Migrations", "Something went wrong when adding column silent to table ChatMessages", e)
}
}
}

View File

@ -51,7 +51,7 @@ import java.util.Locale
ChatMessageEntity::class,
ChatBlockEntity::class
],
version = 17,
version = 18,
autoMigrations = [
AutoMigration(from = 9, to = 10),
AutoMigration(from = 16, to = 17, spec = AutoMigration16To17::class)
@ -112,7 +112,7 @@ abstract class TalkDatabase : RoomDatabase() {
return Room
.databaseBuilder(context.applicationContext, TalkDatabase::class.java, dbName)
// comment out openHelperFactory to view the database entries in Android Studio for debugging
.openHelperFactory(factory)
// .openHelperFactory(factory)
.addMigrations(
Migrations.MIGRATION_6_8,
Migrations.MIGRATION_7_8,
@ -122,7 +122,8 @@ abstract class TalkDatabase : RoomDatabase() {
Migrations.MIGRATION_12_13,
Migrations.MIGRATION_13_14,
Migrations.MIGRATION_14_15,
Migrations.MIGRATION_15_16
Migrations.MIGRATION_15_16,
Migrations.MIGRATION_17_18
)
.allowMainThreadQueries()
.addCallback(

View File

@ -17,6 +17,7 @@ class ConversationModel(
var internalId: String,
var accountId: Long,
var token: String,
var threadId: Long? = null,
var name: String,
var displayName: String,
var description: String,

View File

@ -19,6 +19,8 @@ import kotlinx.parcelize.Parcelize
data class ChatMessageJson(
@JsonField(name = ["id"]) var id: Long = 0,
@JsonField(name = ["token"]) var token: String? = null,
@JsonField(name = ["topmostParentId"]) var topmostParentId: Long? = null,
@JsonField(name = ["childrenCount"]) var childrenCount: Long? = 0,
@JsonField(name = ["actorType"]) var actorType: String? = null,
@JsonField(name = ["actorId"]) var actorId: String? = null,
@JsonField(name = ["actorDisplayName"]) var actorDisplayName: String? = null,

View File

@ -28,6 +28,9 @@ data class Conversation(
@JsonField(name = ["token"])
var token: String = "",
@JsonField(name = ["threadId"])
var threadId: Long? = null,
@JsonField(name = ["name"])
var name: String = "",