Rename package to org.fossify.messages

This commit is contained in:
Naveen 2024-01-18 01:05:03 +05:30
parent d71db351ca
commit e2f83f49da
No known key found for this signature in database
GPG key ID: 0E155DAD31671DA3
106 changed files with 417 additions and 418 deletions

View file

@ -0,0 +1,15 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(
tableName = "archived_conversations",
indices = [(Index(value = ["thread_id"], unique = true))]
)
data class ArchivedConversation(
@PrimaryKey @ColumnInfo(name = "thread_id") var threadId: Long,
@ColumnInfo(name = "deleted_ts") var deletedTs: Long
)

View file

@ -0,0 +1,21 @@
package org.fossify.messages.models
import android.net.Uri
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = "attachments", indices = [(Index(value = ["message_id"], unique = true))])
data class Attachment(
@PrimaryKey(autoGenerate = true) var id: Long?,
@ColumnInfo(name = "message_id") var messageId: Long,
@ColumnInfo(name = "uri_string") var uriString: String,
@ColumnInfo(name = "mimetype") var mimetype: String,
@ColumnInfo(name = "width") var width: Int,
@ColumnInfo(name = "height") var height: Int,
@ColumnInfo(name = "filename") var filename: String
) {
fun getUri() = Uri.parse(uriString)
}

View file

@ -0,0 +1,36 @@
package org.fossify.messages.models
import android.net.Uri
import org.fossify.messages.extensions.isImageMimeType
import org.fossify.messages.extensions.isVCardMimeType
import org.fossify.messages.extensions.isVideoMimeType
import org.fossify.messages.helpers.ATTACHMENT_DOCUMENT
import org.fossify.messages.helpers.ATTACHMENT_MEDIA
import org.fossify.messages.helpers.ATTACHMENT_VCARD
data class AttachmentSelection(
val id: String,
val uri: Uri,
val mimetype: String,
val filename: String,
var isPending: Boolean,
val viewType: Int = getViewTypeForMimeType(mimetype)
) {
companion object {
fun getViewTypeForMimeType(mimetype: String): Int {
return when {
mimetype.isImageMimeType() || mimetype.isVideoMimeType() -> ATTACHMENT_MEDIA
mimetype.isVCardMimeType() -> ATTACHMENT_VCARD
else -> ATTACHMENT_DOCUMENT
}
}
fun areItemsTheSame(first: AttachmentSelection, second: AttachmentSelection): Boolean {
return first.id == second.id
}
fun areContentsTheSame(first: AttachmentSelection, second: AttachmentSelection): Boolean {
return first.uri == second.uri && first.mimetype == second.mimetype && first.filename == second.filename
}
}
}

View file

@ -0,0 +1,13 @@
package org.fossify.messages.models
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
enum class BackupType {
@SerialName("sms")
SMS,
@SerialName("mms")
MMS,
}

View file

@ -0,0 +1,38 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = "conversations", indices = [(Index(value = ["thread_id"], unique = true))])
data class Conversation(
@PrimaryKey @ColumnInfo(name = "thread_id") var threadId: Long,
@ColumnInfo(name = "snippet") var snippet: String,
@ColumnInfo(name = "date") var date: Int,
@ColumnInfo(name = "read") var read: Boolean,
@ColumnInfo(name = "title") var title: String,
@ColumnInfo(name = "photo_uri") var photoUri: String,
@ColumnInfo(name = "is_group_conversation") var isGroupConversation: Boolean,
@ColumnInfo(name = "phone_number") var phoneNumber: String,
@ColumnInfo(name = "is_scheduled") var isScheduled: Boolean = false,
@ColumnInfo(name = "uses_custom_title") var usesCustomTitle: Boolean = false,
@ColumnInfo(name = "archived") var isArchived: Boolean = false
) {
companion object {
fun areItemsTheSame(old: Conversation, new: Conversation): Boolean {
return old.threadId == new.threadId
}
fun areContentsTheSame(old: Conversation, new: Conversation): Boolean {
return old.snippet == new.snippet &&
old.date == new.date &&
old.read == new.read &&
old.title == new.title &&
old.photoUri == new.photoUri &&
old.isGroupConversation == new.isGroupConversation &&
old.phoneNumber == new.phoneNumber
}
}
}

View file

@ -0,0 +1,16 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Embedded
data class ConversationWithSnippetOverride(
@ColumnInfo(name = "new_snippet") val snippet: String?,
@Embedded val conversation: Conversation
) {
fun toConversation() =
if (snippet == null) {
conversation
} else {
conversation.copy(snippet = snippet)
}
}

View file

@ -0,0 +1,5 @@
package org.fossify.messages.models
class Events {
class RefreshMessages
}

View file

@ -0,0 +1,10 @@
package org.fossify.messages.models
import com.google.gson.annotations.SerializedName
data class ExportedMessage(
@SerializedName("sms")
val sms: List<SmsBackup>?,
@SerializedName("mms")
val mms: List<MmsBackup>?,
)

View file

@ -0,0 +1,5 @@
package org.fossify.messages.models
enum class ImportResult {
IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL, IMPORT_NOTHING_NEW
}

View file

@ -0,0 +1,69 @@
package org.fossify.messages.models
import android.provider.Telephony
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.fossify.commons.models.SimpleContact
@Entity(tableName = "messages")
data class Message(
@PrimaryKey val id: Long,
@ColumnInfo(name = "body") val body: String,
@ColumnInfo(name = "type") val type: Int,
@ColumnInfo(name = "status") val status: Int,
@ColumnInfo(name = "participants") val participants: ArrayList<SimpleContact>,
@ColumnInfo(name = "date") val date: Int,
@ColumnInfo(name = "read") val read: Boolean,
@ColumnInfo(name = "thread_id") val threadId: Long,
@ColumnInfo(name = "is_mms") val isMMS: Boolean,
@ColumnInfo(name = "attachment") val attachment: MessageAttachment?,
@ColumnInfo(name = "sender_phone_number") val senderPhoneNumber: String,
@ColumnInfo(name = "sender_name") var senderName: String,
@ColumnInfo(name = "sender_photo_uri") val senderPhotoUri: String,
@ColumnInfo(name = "subscription_id") var subscriptionId: Int,
@ColumnInfo(name = "is_scheduled") var isScheduled: Boolean = false
) : ThreadItem() {
fun isReceivedMessage() = type == Telephony.Sms.MESSAGE_TYPE_INBOX
fun millis() = date * 1000L
fun getSender(): SimpleContact? =
participants.firstOrNull { it.doesHavePhoneNumber(senderPhoneNumber) }
?: participants.firstOrNull { it.name == senderName }
?: participants.firstOrNull()
companion object {
fun getStableId(message: Message): Long {
var result = message.id.hashCode()
result = 31 * result + message.body.hashCode()
result = 31 * result + message.date.hashCode()
result = 31 * result + message.threadId.hashCode()
result = 31 * result + message.isMMS.hashCode()
result = 31 * result + (message.attachment?.hashCode() ?: 0)
result = 31 * result + message.senderPhoneNumber.hashCode()
result = 31 * result + message.senderName.hashCode()
result = 31 * result + message.senderPhotoUri.hashCode()
result = 31 * result + message.isScheduled.hashCode()
return result.toLong()
}
fun areItemsTheSame(old: Message, new: Message): Boolean {
return old.id == new.id
}
fun areContentsTheSame(old: Message, new: Message): Boolean {
return old.body == new.body &&
old.threadId == new.threadId &&
old.date == new.date &&
old.isMMS == new.isMMS &&
old.attachment == new.attachment &&
old.senderPhoneNumber == new.senderPhoneNumber &&
old.senderName == new.senderName &&
old.senderPhotoUri == new.senderPhotoUri &&
old.isScheduled == new.isScheduled
}
}
}

View file

@ -0,0 +1,12 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "message_attachments")
data class MessageAttachment(
@PrimaryKey val id: Long,
@ColumnInfo(name = "text") var text: String,
@ColumnInfo(name = "attachments") var attachments: ArrayList<Attachment>
)

View file

@ -0,0 +1,27 @@
package org.fossify.messages.models
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
@Serializable(with = BackupSerializer::class)
sealed class MessagesBackup {
@SerialName("backupType")
abstract val backupType: BackupType
}
object BackupSerializer :
JsonContentPolymorphicSerializer<MessagesBackup>(MessagesBackup::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out MessagesBackup> {
return when (element.jsonObject["backupType"]?.jsonPrimitive?.content) {
"sms" -> SmsBackup.serializer()
"mms" -> MmsBackup.serializer()
else -> throw SerializationException("ERROR: No Serializer found. Serialization failed.")
}
}
}

View file

@ -0,0 +1,28 @@
package org.fossify.messages.models
import android.content.ContentValues
import android.provider.Telephony
import androidx.core.content.contentValuesOf
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class MmsAddress(
@SerializedName("address")
val address: String,
@SerializedName("type")
val type: Int,
@SerializedName("charset")
val charset: Int
) {
fun toContentValues(): ContentValues {
// msgId would be added at the point of insertion
// because it may have changed
return contentValuesOf(
Telephony.Mms.Addr.ADDRESS to address,
Telephony.Mms.Addr.TYPE to type,
Telephony.Mms.Addr.CHARSET to charset,
)
}
}

View file

@ -0,0 +1,73 @@
package org.fossify.messages.models
import android.content.ContentValues
import android.provider.Telephony
import androidx.core.content.contentValuesOf
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class MmsBackup(
@SerializedName("creator")
val creator: String?,
@SerializedName("ct_t")
val contentType: String?,
@SerializedName("d_rpt")
val deliveryReport: Int,
@SerializedName("date")
val date: Long,
@SerializedName("date_sent")
val dateSent: Long,
@SerializedName("locked")
val locked: Int,
@SerializedName("m_type")
val messageType: Int,
@SerializedName("msg_box")
val messageBox: Int,
@SerializedName("read")
val read: Int,
@SerializedName("rr")
val readReport: Int,
@SerializedName("seen")
val seen: Int,
@SerializedName("text_only")
val textOnly: Int,
@SerializedName("st")
val status: String?,
@SerializedName("sub")
val subject: String?,
@SerializedName("sub_cs")
val subjectCharSet: String?,
@SerializedName("sub_id")
val subscriptionId: Long,
@SerializedName("tr_id")
val transactionId: String?,
@SerializedName("addresses")
val addresses: List<MmsAddress>,
@SerializedName("parts")
val parts: List<MmsPart>,
override val backupType: BackupType = BackupType.MMS,
) : MessagesBackup() {
fun toContentValues(): ContentValues {
return contentValuesOf(
Telephony.Mms.TRANSACTION_ID to transactionId,
Telephony.Mms.SUBSCRIPTION_ID to subscriptionId,
Telephony.Mms.SUBJECT to subject,
Telephony.Mms.DATE to date,
Telephony.Mms.DATE_SENT to dateSent,
Telephony.Mms.LOCKED to locked,
Telephony.Mms.READ to read,
Telephony.Mms.STATUS to status,
Telephony.Mms.SUBJECT_CHARSET to subjectCharSet,
Telephony.Mms.SEEN to seen,
Telephony.Mms.MESSAGE_TYPE to messageType,
Telephony.Mms.MESSAGE_BOX to messageBox,
Telephony.Mms.DELIVERY_REPORT to deliveryReport,
Telephony.Mms.READ_REPORT to readReport,
Telephony.Mms.CONTENT_TYPE to contentType,
Telephony.Mms.TEXT_ONLY to textOnly,
)
}
}

View file

@ -0,0 +1,56 @@
package org.fossify.messages.models
import android.content.ContentValues
import android.provider.Telephony
import androidx.core.content.contentValuesOf
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class MmsPart(
@SerializedName("cd")
val contentDisposition: String?,
@SerializedName("chset")
val charset: String?,
@SerializedName("cid")
val contentId: String?,
@SerializedName("cl")
val contentLocation: String?,
@SerializedName("ct")
val contentType: String,
@SerializedName("ctt_s")
val ctStart: String?,
@SerializedName("ctt_t")
val ctType: String?,
@SerializedName("fn")
val filename: String?,
@SerializedName("name")
val name: String?,
@SerializedName("seq")
val sequenceOrder: Int,
@SerializedName("text")
val text: String?,
@SerializedName("data")
val data: String?,
) {
fun toContentValues(): ContentValues {
return contentValuesOf(
Telephony.Mms.Part.CONTENT_DISPOSITION to contentDisposition,
Telephony.Mms.Part.CHARSET to charset,
Telephony.Mms.Part.CONTENT_ID to contentId,
Telephony.Mms.Part.CONTENT_LOCATION to contentLocation,
Telephony.Mms.Part.CONTENT_TYPE to contentType,
Telephony.Mms.Part.CT_START to ctStart,
Telephony.Mms.Part.CT_TYPE to ctType,
Telephony.Mms.Part.FILENAME to filename,
Telephony.Mms.Part.NAME to name,
Telephony.Mms.Part.SEQ to sequenceOrder,
Telephony.Mms.Part.TEXT to text,
)
}
fun isNonText(): Boolean {
return !(text != null || contentType.lowercase().startsWith("text") || contentType.lowercase() == "application/smil")
}
}

View file

@ -0,0 +1,3 @@
package org.fossify.messages.models
data class NamePhoto(val name: String, val photoUri: String?)

View file

@ -0,0 +1,15 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(
tableName = "recycle_bin_messages",
indices = [(Index(value = ["id"], unique = true))]
)
data class RecycleBinMessage(
@PrimaryKey val id: Long,
@ColumnInfo(name = "deleted_ts") var deletedTS: Long
)

View file

@ -0,0 +1,3 @@
package org.fossify.messages.models
data class SIMCard(val id: Int, val subscriptionId: Int, val label: String)

View file

@ -0,0 +1,3 @@
package org.fossify.messages.models
data class SearchResult(val messageId: Long, val title: String, val snippet: String, val date: String, val threadId: Long, var photoUri: String)

View file

@ -0,0 +1,53 @@
package org.fossify.messages.models
import android.content.ContentValues
import android.provider.Telephony
import androidx.core.content.contentValuesOf
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class SmsBackup(
@SerializedName("sub_id")
val subscriptionId: Long,
@SerializedName("address")
val address: String,
@SerializedName("body")
val body: String?,
@SerializedName("date")
val date: Long,
@SerializedName("date_sent")
val dateSent: Long,
@SerializedName("locked")
val locked: Int,
@SerializedName("protocol")
val protocol: String?,
@SerializedName("read")
val read: Int,
@SerializedName("status")
val status: Int,
@SerializedName("type")
val type: Int,
@SerializedName("service_center")
val serviceCenter: String?,
override val backupType: BackupType = BackupType.SMS,
) : MessagesBackup() {
fun toContentValues(): ContentValues {
return contentValuesOf(
Telephony.Sms.SUBSCRIPTION_ID to subscriptionId,
Telephony.Sms.ADDRESS to address,
Telephony.Sms.BODY to body,
Telephony.Sms.DATE to date,
Telephony.Sms.DATE_SENT to dateSent,
Telephony.Sms.LOCKED to locked,
Telephony.Sms.PROTOCOL to protocol,
Telephony.Sms.READ to read,
Telephony.Sms.STATUS to status,
Telephony.Sms.TYPE to type,
Telephony.Sms.SERVICE_CENTER to serviceCenter,
)
}
}

View file

@ -0,0 +1,12 @@
package org.fossify.messages.models
/**
* Thread item representations for the main thread recyclerview. [Message] is also a [ThreadItem]
*/
sealed class ThreadItem {
data class ThreadLoading(val id: Long) : ThreadItem()
data class ThreadDateTime(val date: Int, val simID: String) : ThreadItem()
data class ThreadError(val messageId: Long, val messageText: String) : ThreadItem()
data class ThreadSent(val messageId: Long, val delivered: Boolean) : ThreadItem()
data class ThreadSending(val messageId: Long) : ThreadItem()
}

View file

@ -0,0 +1,76 @@
package org.fossify.messages.models
import android.content.Context
import ezvcard.VCard
import ezvcard.property.*
import org.fossify.commons.extensions.normalizePhoneNumber
import org.fossify.messages.extensions.config
import org.fossify.messages.extensions.format
import org.fossify.messages.helpers.parseNameFromVCard
private val displayedPropertyClasses = arrayOf(
Telephone::class.java, Email::class.java, Organization::class.java, Birthday::class.java, Anniversary::class.java, Note::class.java
)
data class VCardWrapper(val vCard: VCard, val fullName: String?, val properties: List<VCardPropertyWrapper>, var expanded: Boolean = false) {
companion object {
fun from(context: Context, vCard: VCard): VCardWrapper {
val properties = vCard.properties
.filter { displayedPropertyClasses.contains(it::class.java) }
.map { VCardPropertyWrapper.from(context, it) }
.distinctBy { it.value }
val fullName = vCard.parseNameFromVCard()
return VCardWrapper(vCard, fullName, properties)
}
}
}
data class VCardPropertyWrapper(val value: String, val type: String, val property: VCardProperty) {
companion object {
private const val CELL = "CELL"
private const val HOME = "HOME"
private const val WORK = "WORK"
private fun VCardProperty.getPropertyTypeString(context: Context): String {
return when (parameters.type) {
CELL -> context.getString(org.fossify.commons.R.string.mobile)
HOME -> context.getString(org.fossify.commons.R.string.home)
WORK -> context.getString(org.fossify.commons.R.string.work)
else -> ""
}
}
fun from(context: Context, property: VCardProperty): VCardPropertyWrapper {
return property.run {
when (this) {
is Telephone -> VCardPropertyWrapper(text.normalizePhoneNumber(), getPropertyTypeString(context), property)
is Email -> VCardPropertyWrapper(value, getPropertyTypeString(context), property)
is Organization -> VCardPropertyWrapper(
value = values.joinToString(),
type = context.getString(org.fossify.commons.R.string.work),
property = property
)
is Birthday -> VCardPropertyWrapper(
value = date.format(context.config.dateFormat),
type = context.getString(org.fossify.commons.R.string.birthday),
property = property
)
is Anniversary -> VCardPropertyWrapper(
value = date.format(context.config.dateFormat),
type = context.getString(org.fossify.commons.R.string.anniversary),
property = property
)
is Note -> VCardPropertyWrapper(value, context.getString(org.fossify.commons.R.string.notes), property)
else -> VCardPropertyWrapper("", "", property)
}
}
}
}
}