Skip to content

Commit

Permalink
refactor: relation db and other changes
Browse files Browse the repository at this point in the history
  • Loading branch information
andrekir committed Dec 3, 2024
1 parent ad6746e commit 1ead40c
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 336 deletions.
47 changes: 30 additions & 17 deletions app/schemas/com.geeksville.mesh.database.MeshtasticDatabase/14.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 14,
"identityHash": "39c7546c92fbdd0c05e7cfed2a4eed98",
"identityHash": "b610881191518f933ee6bb694d12d0a2",
"entities": [
{
"tableName": "my_node",
Expand Down Expand Up @@ -202,7 +202,7 @@
},
{
"tableName": "packet",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `myNodeNum` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL, `contact_key` TEXT NOT NULL, `received_time` INTEGER NOT NULL, `read` INTEGER NOT NULL DEFAULT 1, `data` TEXT NOT NULL, `packet_id` INTEGER NOT NULL DEFAULT 0, `routing_error` INTEGER NOT NULL DEFAULT -1)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `myNodeNum` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL, `contact_key` TEXT NOT NULL, `received_time` INTEGER NOT NULL, `read` INTEGER NOT NULL DEFAULT 1, `data` TEXT NOT NULL, `packet_id` INTEGER NOT NULL DEFAULT 0, `routing_error` INTEGER NOT NULL DEFAULT -1, `reply_id` INTEGER NOT NULL DEFAULT 0)",
"fields": [
{
"fieldPath": "uuid",
Expand Down Expand Up @@ -261,6 +261,13 @@
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "replyId",
"columnName": "reply_id",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
}
],
"primaryKey": {
Expand Down Expand Up @@ -449,24 +456,18 @@
"foreignKeys": []
},
{
"tableName": "tapbacks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `messageId` INTEGER NOT NULL, `userId` TEXT NOT NULL, `emoji` TEXT NOT NULL, `timestamp` INTEGER NOT NULL)",
"tableName": "reactions",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`reply_id` INTEGER NOT NULL, `user_id` TEXT NOT NULL, `emoji` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`reply_id`, `user_id`, `emoji`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "messageId",
"columnName": "messageId",
"fieldPath": "replyId",
"columnName": "reply_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"columnName": "user_id",
"affinity": "TEXT",
"notNull": true
},
Expand All @@ -484,19 +485,31 @@
}
],
"primaryKey": {
"autoGenerate": true,
"autoGenerate": false,
"columnNames": [
"id"
"reply_id",
"user_id",
"emoji"
]
},
"indices": [],
"indices": [
{
"name": "index_reactions_reply_id",
"unique": false,
"columnNames": [
"reply_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_reactions_reply_id` ON `${TABLE_NAME}` (`reply_id`)"
}
],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"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, '39c7546c92fbdd0c05e7cfed2a4eed98')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b610881191518f933ee6bb694d12d0a2')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.geeksville.mesh.database.entity.MyNodeEntity
import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.QuickChatAction
import com.geeksville.mesh.database.entity.TapBack
import com.geeksville.mesh.database.entity.ReactionEntity

@Database(
entities = [
Expand All @@ -28,7 +28,7 @@ import com.geeksville.mesh.database.entity.TapBack
ContactSettings::class,
MeshLog::class,
QuickChatAction::class,
TapBack::class,
ReactionEntity::class,
],
autoMigrations = [
AutoMigration(from = 3, to = 4),
Expand All @@ -41,7 +41,7 @@ import com.geeksville.mesh.database.entity.TapBack
AutoMigration(from = 10, to = 11),
AutoMigration(from = 11, to = 12),
AutoMigration(from = 12, to = 13, spec = AutoMigration12to13::class),
AutoMigration(from = 13, to = 14), // add TapBack
AutoMigration(from = 13, to = 14),
],
version = 14,
exportSchema = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.geeksville.mesh.Portnums.PortNum
import com.geeksville.mesh.database.dao.PacketDao
import com.geeksville.mesh.database.entity.ContactSettings
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.TapBack
import com.geeksville.mesh.database.entity.ReactionEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -68,13 +68,6 @@ class PacketRepository @Inject constructor(private val packetDaoLazy: dagger.Laz
packetDao.updateMessageId(d, id)
}

suspend fun insertTapBack(tapBack: TapBack) = withContext(Dispatchers.IO) {
packetDao.insertTapBack(tapBack)
}
suspend fun getTapBacksForMessage(messageId: Int) = withContext(Dispatchers.IO) {
packetDao.getTapBacksForMessage(messageId)
}

suspend fun getPacketById(requestId: Int) = withContext(Dispatchers.IO) {
packetDao.getPacketById(requestId)
}
Expand Down Expand Up @@ -110,4 +103,8 @@ class PacketRepository @Inject constructor(private val packetDaoLazy: dagger.Laz
suspend fun setMuteUntil(contacts: List<String>, until: Long) = withContext(Dispatchers.IO) {
packetDao.setMuteUntil(contacts, until)
}

suspend fun insertReaction(reaction: ReactionEntity) = withContext(Dispatchers.IO) {
packetDao.insert(reaction)
}
}
61 changes: 37 additions & 24 deletions app/src/main/java/com/geeksville/mesh/database/dao/PacketDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package com.geeksville.mesh.database.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.MapColumn
import androidx.room.Update
import androidx.room.Query
Expand All @@ -27,8 +26,9 @@ import androidx.room.Upsert
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MessageStatus
import com.geeksville.mesh.database.entity.ContactSettings
import com.geeksville.mesh.database.entity.PacketEntity
import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.TapBack
import com.geeksville.mesh.database.entity.ReactionEntity
import kotlinx.coroutines.flow.Flow

@Dao
Expand Down Expand Up @@ -82,8 +82,8 @@ interface PacketDao {
)
suspend fun clearUnreadCount(contact: String, timestamp: Long)

@Insert
fun insert(packet: Packet)
@Upsert
suspend fun insert(packet: Packet)

@Query(
"""
Expand All @@ -93,7 +93,8 @@ interface PacketDao {
ORDER BY received_time DESC
"""
)
fun getMessagesFrom(contact: String): Flow<List<Packet>>
@Transaction
fun getMessagesFrom(contact: String): Flow<List<PacketEntity>>

@Query(
"""
Expand All @@ -102,10 +103,10 @@ interface PacketDao {
AND data = :data
"""
)
fun findDataPacket(data: DataPacket): Packet?
suspend fun findDataPacket(data: DataPacket): Packet?

@Query("DELETE FROM packet WHERE uuid in (:uuidList)")
fun deleteMessages(uuidList: List<Long>)
suspend fun deletePackets(uuidList: List<Long>)

@Query(
"""
Expand All @@ -114,27 +115,42 @@ interface PacketDao {
AND contact_key IN (:contactList)
"""
)
fun deleteContacts(contactList: List<String>)
suspend fun deleteContacts(contactList: List<String>)

@Query("DELETE FROM packet WHERE uuid=:uuid")
fun _delete(uuid: Long)
suspend fun _delete(uuid: Long)

@Transaction
fun delete(packet: Packet) {
suspend fun delete(packet: Packet) {
_delete(packet.uuid)
}

@Query("SELECT packet_id FROM packet WHERE uuid IN (:uuidList)")
suspend fun getPacketIdsFrom(uuidList: List<Long>): List<Int>

@Query("DELETE FROM reactions WHERE reply_id IN (:packetIds)")
suspend fun deleteReactions(packetIds: List<Int>)

@Transaction
suspend fun deleteMessages(uuidList: List<Long>) {
val packetIds = getPacketIdsFrom(uuidList)
if (packetIds.isNotEmpty()) {
deleteReactions(packetIds)
}
deletePackets(uuidList)
}

@Update
fun update(packet: Packet)
suspend fun update(packet: Packet)

@Transaction
fun updateMessageStatus(data: DataPacket, m: MessageStatus) {
suspend fun updateMessageStatus(data: DataPacket, m: MessageStatus) {
val new = data.copy(status = m)
findDataPacket(data)?.let { update(it.copy(data = new)) }
}

@Transaction
fun updateMessageId(data: DataPacket, id: Int) {
suspend fun updateMessageId(data: DataPacket, id: Int) {
val new = data.copy(id = id)
findDataPacket(data)?.let { update(it.copy(data = new)) }
}
Expand All @@ -146,7 +162,7 @@ interface PacketDao {
ORDER BY received_time ASC
"""
)
fun getDataPackets(): List<DataPacket>
suspend fun getDataPackets(): List<DataPacket>

@Query(
"""
Expand All @@ -156,10 +172,10 @@ interface PacketDao {
ORDER BY received_time DESC
"""
)
fun getPacketById(requestId: Int): Packet?
suspend fun getPacketById(requestId: Int): Packet?

@Transaction
fun getQueuedPackets(): List<DataPacket>? =
suspend fun getQueuedPackets(): List<DataPacket>? =
getDataPackets().filter { it.status == MessageStatus.QUEUED }

@Query(
Expand All @@ -170,10 +186,10 @@ interface PacketDao {
ORDER BY received_time ASC
"""
)
fun getAllWaypoints(): List<Packet>
suspend fun getAllWaypoints(): List<Packet>

@Transaction
fun deleteWaypoint(id: Int) {
suspend fun deleteWaypoint(id: Int) {
val uuidList = getAllWaypoints().filter { it.data.waypoint?.id == id }.map { it.uuid }
deleteMessages(uuidList)
}
Expand All @@ -185,7 +201,7 @@ interface PacketDao {
suspend fun getContactSettings(contact: String): ContactSettings?

@Upsert
fun upsertContactSettings(contacts: List<ContactSettings>)
suspend fun upsertContactSettings(contacts: List<ContactSettings>)

@Transaction
suspend fun setMuteUntil(contacts: List<String>, until: Long) {
Expand All @@ -196,9 +212,6 @@ interface PacketDao {
upsertContactSettings(contactList)
}

@Query("SELECT * FROM tapbacks WHERE messageId = :messageId")
fun getTapBacksForMessage(messageId: Int): List<TapBack>?

@Insert
fun insertTapBack(tapBack: TapBack)
@Upsert
suspend fun insert(reaction: ReactionEntity)
}
61 changes: 61 additions & 0 deletions app/src/main/java/com/geeksville/mesh/database/entity/Packet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,36 @@
package com.geeksville.mesh.database.entity

import androidx.room.ColumnInfo
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import androidx.room.Relation
import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MeshProtos.User
import com.geeksville.mesh.model.Message
import com.geeksville.mesh.util.getShortDateTime

data class PacketEntity(
@Embedded val packet: Packet,
@Relation(entity = ReactionEntity::class, parentColumn = "packet_id", entityColumn = "reply_id")
val reactions: List<ReactionEntity> = emptyList(),
) {
suspend fun toMessage(getUser: suspend (userId: String?) -> User) = with(packet) {
Message(
uuid = uuid,
receivedTime = received_time,
user = getUser(data.from),
text = data.text.orEmpty(),
time = getShortDateTime(data.time),
read = read,
status = data.status,
routingError = routingError,
packetId = packetId,
emojis = reactions.toReaction(getUser),
)
}
}

@Entity(
tableName = "packet",
Expand All @@ -42,6 +68,7 @@ data class Packet(
@ColumnInfo(name = "data") val data: DataPacket,
@ColumnInfo(name = "packet_id", defaultValue = "0") val packetId: Int = 0,
@ColumnInfo(name = "routing_error", defaultValue = "-1") var routingError: Int = -1,
@ColumnInfo(name = "reply_id", defaultValue = "0") val replyId: Int = 0,
)

@Entity(tableName = "contact_settings")
Expand All @@ -51,3 +78,37 @@ data class ContactSettings(
) {
val isMuted get() = System.currentTimeMillis() <= muteUntil
}

data class Reaction(
val replyId: Int,
val user: User,
val emoji: String,
val timestamp: Long,
)

@Entity(
tableName = "reactions",
primaryKeys = ["reply_id", "user_id", "emoji"],
indices = [
Index(value = ["reply_id"]),
],
)
data class ReactionEntity(
@ColumnInfo(name = "reply_id") val replyId: Int,
@ColumnInfo(name = "user_id") val userId: String,
val emoji: String,
val timestamp: Long,
)

private suspend fun ReactionEntity.toReaction(
getUser: suspend (userId: String?) -> User
) = Reaction(
replyId = replyId,
user = getUser(userId),
emoji = emoji,
timestamp = timestamp,
)

private suspend fun List<ReactionEntity>.toReaction(
getUser: suspend (userId: String?) -> User
) = this.map { it.toReaction(getUser) }
Loading

0 comments on commit 1ead40c

Please sign in to comment.