Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class MediaRepository @Inject constructor(
private val pathUtil: PathUtil,
) {
companion object {
private const val TAG = "PackageRepository"
private val TAG = this::class.java.simpleName
}

private fun log(onMsg: () -> String): String = run {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.xayah.core.data.repository

import android.content.Context
import com.xayah.core.database.dao.MessageDao
import com.xayah.core.model.CompressionType
import com.xayah.core.model.OpType
import com.xayah.core.model.database.MediaEntity
import com.xayah.core.model.database.MessageEntity
import com.xayah.core.rootservice.service.RemoteRootService
import com.xayah.core.util.LogUtil
import com.xayah.core.util.PathUtil
import com.xayah.core.util.localBackupSaveDir
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.distinctUntilChanged
import javax.inject.Inject

class MessagesRepository @Inject constructor(
@ApplicationContext private val context: Context,
private val rootService: RemoteRootService,
private val cloudRepository: CloudRepository,
private val messageDao: MessageDao,
private val pathUtil: PathUtil,
) {
companion object {
private val TAG = this::class.java.simpleName
}

private fun log(onMsg: () -> String): String = run {
val msg = onMsg()
LogUtil.log { TAG to msg }
msg
}

fun queryFlow(opType: OpType) = messageDao.queryFlow(opType).distinctUntilChanged()
suspend fun query(opType: OpType) = messageDao.query(opType)
suspend fun upsert(item: MessageEntity) = messageDao.upsert(item)
suspend fun upsert(items: List<MessageEntity>) = messageDao.upsert(items)
suspend fun delete(id: Long) = messageDao.delete(id)
suspend fun queryActivated(opType: OpType) = messageDao.queryActivated(opType)
suspend fun queryActivated(opType: OpType, cloud: String, backupDir: String) = messageDao.queryActivated(opType, cloud, backupDir)
suspend fun query(opType: OpType, preserveId: Long, name: String, cloud: String, backupDir: String) = messageDao.query(opType, preserveId, name, cloud, backupDir)
suspend fun query(opType: OpType, preserveId: Long, name: String, ct: CompressionType, cloud: String, backupDir: String) = messageDao.query(opType, preserveId, name, ct, cloud, backupDir)
suspend fun query(opType: OpType, name: String, cloud: String, backupDir: String) = messageDao.query(opType, name, cloud, backupDir)
suspend fun query(opType: OpType, preserveId: Long, cloud: String, backupDir: String) = messageDao.query(opType, preserveId, cloud, backupDir)
suspend fun query(opType: OpType, cloud: String, backupDir: String) = messageDao.query(opType, cloud, backupDir)
suspend fun query(name: String, opType: OpType) = messageDao.query(name, opType)

private val localBackupSaveDir get() = context.localBackupSaveDir()
val backupMessagesDir get() = pathUtil.getLocalMessagesDir()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.xayah.core.database.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Query
import androidx.room.Update
import androidx.room.Upsert
import com.xayah.core.model.CompressionType
import com.xayah.core.model.OpType
import com.xayah.core.model.database.MessageEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface MessageDao {
@Upsert(entity = MessageEntity::class)
suspend fun upsert(items: List<MessageEntity>)

@Upsert(entity = MessageEntity::class)
suspend fun upsert(item: MessageEntity)

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_opType = :opType"
)
suspend fun query(opType: OpType): List<MessageEntity>

@Query(
"SELECT * FROM MessageEntity" +
" WHERE indexInfo_opType = :opType AND indexInfo_preserveId = :preserveId" +
" AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir"
)
suspend fun query(opType: OpType, preserveId: Long, cloud: String, backupDir: String): List<MessageEntity>

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_opType = :opType AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir"
)
suspend fun query(opType: OpType, cloud: String, backupDir: String): List<MessageEntity>

@Query(
"SELECT * FROM MessageEntity" +
" WHERE indexInfo_opType = :opType AND indexInfo_name = :name" +
" AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir"
)
suspend fun query(opType: OpType, name: String, cloud: String, backupDir: String): List<MessageEntity>

@Query(
"SELECT * FROM MessageEntity" +
" WHERE indexInfo_opType = :opType AND indexInfo_preserveId = :preserveId AND indexInfo_name = :name" +
" AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir" +
" LIMIT 1"
)
suspend fun query(opType: OpType, preserveId: Long, name: String, cloud: String, backupDir: String): MessageEntity?

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_name = :name AND indexInfo_opType = :opType" +
" LIMIT 1"
)
suspend fun query(name: String, opType: OpType): MessageEntity?

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_opType = :opType AND indexInfo_preserveId = :preserveId AND indexInfo_name = :name AND indexInfo_compressionType = :ct" +
" AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir" +
" LIMIT 1"
)
suspend fun query(opType: OpType, preserveId: Long, name: String, ct: CompressionType, cloud: String, backupDir: String): MessageEntity?

@Query("SELECT * FROM MessageEntity WHERE indexInfo_opType = :opType")
suspend fun queryActivated(opType: OpType): List<MessageEntity>

@Query("SELECT * FROM MessageEntity WHERE indexInfo_opType = :opType AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir")
suspend fun queryActivated(opType: OpType, cloud: String, backupDir: String): List<MessageEntity>

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_opType = :opType"
)
fun queryFlow(opType: OpType): Flow<List<MessageEntity>>

@Query(
"SELECT * FROM MessageEntity WHERE" +
" indexInfo_opType = :opType AND indexInfo_cloud = :cloud AND indexInfo_backupDir = :backupDir"
)
fun queryFlow(opType: OpType, cloud: String, backupDir: String): Flow<List<MessageEntity>>

@Query("SELECT * FROM MessageEntity WHERE indexInfo_opType = :opType AND indexInfo_preserveId = :preserveId")
fun queryFlow(opType: OpType, preserveId: Long): Flow<List<MessageEntity>>

@Query("SELECT * FROM MessageEntity WHERE indexInfo_name = :name AND indexInfo_opType = :opType AND indexInfo_preserveId = :preserveId LIMIT 1")
fun queryFlow(name: String, opType: OpType, preserveId: Long): Flow<MessageEntity?>

@Query("SELECT * FROM MessageEntity WHERE indexInfo_name = :name AND indexInfo_opType = :opType")
fun queryFlow(name: String, opType: OpType): Flow<List<MessageEntity>>

@Query("SELECT COUNT(*) FROM MessageEntity")
suspend fun count(): Long

@Delete(entity = MessageEntity::class)
suspend fun delete(item: MessageEntity)

@Query("DELETE FROM MessageEntity WHERE id = :id")
suspend fun delete(id: Long)

@Query("DELETE FROM MessageEntity WHERE id in (:ids)")
suspend fun delete(ids: List<Long>)

@Update(MessageEntity::class)
suspend fun update(item: MessageEntity)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import com.xayah.core.model.ProcessingType
import com.xayah.core.model.database.MessageEntity
import com.xayah.core.model.database.ProcessingInfoEntity
import com.xayah.core.model.database.TaskDetailMediaEntity
import com.xayah.core.model.database.TaskDetailMessageEntity
import com.xayah.core.model.database.TaskDetailPackageEntity
import com.xayah.core.model.database.TaskEntity
import kotlinx.coroutines.flow.Flow
Expand All @@ -21,9 +23,15 @@ interface TaskDao {
@Upsert(entity = TaskDetailMediaEntity::class)
suspend fun upsert(item: TaskDetailMediaEntity): Long

@Upsert(entity = TaskDetailMessageEntity::class)
suspend fun upsert(item: TaskDetailMessageEntity): Long

@Upsert(entity = ProcessingInfoEntity::class)
suspend fun upsert(item: ProcessingInfoEntity): Long

@Upsert(entity = MessageEntity::class)
suspend fun upsert(item: MessageEntity): Long

@Query("SELECT * FROM TaskEntity WHERE id = :id LIMIT 1")
fun queryTaskFlow(id: Long): Flow<TaskEntity?>

Expand Down
30 changes: 28 additions & 2 deletions source/core/model/src/main/kotlin/com/xayah/core/model/Enum.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.xayah.core.model

import android.content.Context
import android.provider.Telephony

const val TAR_SUFFIX = "tar"
const val ZSTD_SUFFIX = "tar.zst"
Expand Down Expand Up @@ -37,7 +38,8 @@ enum class OpType {

enum class TaskType {
PACKAGE,
MEDIA;
MEDIA,
MESSAGE;

companion object
}
Expand Down Expand Up @@ -169,4 +171,28 @@ enum class ProcessingInfoType {
BACKUP_ITSELF,
SAVE_ICONS,
SET_UP_INST_ENV,
}
}

enum class MessageType {
SMS,
MMS,
}

enum class SMSMessageBox(val type: Int) {
ALL(Telephony.Sms.MESSAGE_TYPE_ALL),
DRAFT(Telephony.Sms.MESSAGE_TYPE_DRAFT),
FAILED(Telephony.Sms.MESSAGE_TYPE_FAILED),
INBOX(Telephony.Sms.MESSAGE_TYPE_INBOX),
OUTBOX(Telephony.Sms.MESSAGE_TYPE_OUTBOX),
QUEUED(Telephony.Sms.MESSAGE_TYPE_QUEUED),
SENT(Telephony.Sms.MESSAGE_TYPE_SENT),
}

enum class MMSMessageBox(val type: Int) {
ALL(Telephony.Mms.MESSAGE_BOX_ALL),
DRAFTS(Telephony.Mms.MESSAGE_BOX_DRAFTS),
FAILED(Telephony.Mms.MESSAGE_BOX_FAILED),
INBOX(Telephony.Mms.MESSAGE_BOX_INBOX),
OUTBOX(Telephony.Mms.MESSAGE_BOX_OUTBOX),
SENT(Telephony.Mms.MESSAGE_BOX_SENT),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.xayah.core.model.database

import androidx.room.ColumnInfo
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.xayah.core.model.CompressionType
import com.xayah.core.model.MMSMessageBox
import com.xayah.core.model.MessageType
import com.xayah.core.model.OpType
import com.xayah.core.model.SMSMessageBox
import kotlinx.serialization.Serializable

interface BaseMessageTypeInfo

@Serializable
data class MessageIndexInfo(
var opType: OpType,
var name: String,
var compressionType: CompressionType,
var preserveId: Long,
var cloud: String,
var backupDir: String,
var messageType: MessageType,
)

data class MMSTypeInfo(
val id: Long,
val contentClass: Long,
val contentLocation: String,
val contentType: String,
val deliveryReport: Long,
val deliveryTime: Long,
val expiry: Long,
val messageBox: MMSMessageBox,
val messageClass: String,
val messageId: String,
val messageSize: Long,
val messageType: Long,
val mmsVersion: Long,
val priority: Long,
val readReport: Long,
val readStatus: Long,
val reportAllowed: Long,
val responseStatus: Long,
val responseText: String,
val retrieveStatus: Long,
val retrieveText: String,
val retrieveTextCharset: Long,
val subjectCharset: Long,
val textOnly: Long,
val threadId: Long,
val transactionId: String,

// Mms.Part
val filename: String,
) : BaseMessageTypeInfo

data class SMSTypeInfo(
val creator: String,
val errorCode: Long,
val person: Long,
val protocol: Long,
val replyPathPresent: Long,
val serviceCenter: String,
val type: SMSMessageBox,
) : BaseMessageTypeInfo

@Serializable
data class MessageBaseInfo(
val address: String,
val body: String, // SMS: body, MMS: text
val date: Long,
val dateSent: Long,
val locked: Long,
val read: Long,
val seen: Long,
val status: Long,
val subject: String,
val subscriptionId: Long,
)

@Serializable
data class MessageToggleInfo(
var blocked: Boolean,
var activated: Boolean,
var existed: Boolean,
)

@Serializable
@Entity
data class MessageEntity(
@PrimaryKey(autoGenerate = true) var id: Long,
@ColumnInfo(defaultValue = "0") var processingIndex: Int = 0,
@Embedded(prefix = "indexInfo_") var indexInfo: MessageIndexInfo,
@Embedded(prefix = "baseInfo_") var messageBaseInfo: MessageBaseInfo,
@Embedded(prefix = "typeInfo_") var messageTypeInfo: BaseMessageTypeInfo,
@Embedded(prefix = "toggleInfo_") var messageToggleInfo: MessageToggleInfo,
) {
fun asString(): String {
return Gson().let {
it.toJson(
mapOf(
Pair("baseInfo", it.toJsonTree(messageBaseInfo)),
Pair("typeInfo", it.toJsonTree(messageTypeInfo)),
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ data class TaskDetailMediaEntity(
}
}

@Entity
data class TaskDetailMessageEntity(
@PrimaryKey(autoGenerate = true) var id: Long = 0,
var taskId: Long,
var state: OperationState = OperationState.IDLE,
@ColumnInfo(defaultValue = "0") var processingIndex: Int = 0,
@Embedded(prefix = "messageEntity_") var messageEntity: MessageEntity,
)

@Entity
data class ProcessingInfoEntity(
@PrimaryKey(autoGenerate = true) var id: Long = 0,
Expand Down
Loading
Loading