Commit 76b6fe16 authored by Lucio Maciel's avatar Lucio Maciel

Fixed merging issues and save attachments

parent c63e1da7
...@@ -152,6 +152,8 @@ dependencies { ...@@ -152,6 +152,8 @@ dependencies {
implementation libraries.livedataKtx implementation libraries.livedataKtx
implementation 'com.google.code.findbugs:jsr305:3.0.2'
// Proprietary libraries // Proprietary libraries
playImplementation libraries.fcm playImplementation libraries.fcm
playImplementation libraries.firebaseAnalytics playImplementation libraries.firebaseAnalytics
......
{
"formatVersion": 1,
"database": {
"version": 6,
"identityHash": "03aec453cb4faec2d1357fdb673b151e",
"entities": [
{
"tableName": "users",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `username` TEXT, `name` TEXT, `status` TEXT NOT NULL, `utcOffset` REAL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "utcOffset",
"columnName": "utcOffset",
"affinity": "REAL",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_users_username",
"unique": false,
"columnNames": [
"username"
],
"createSql": "CREATE INDEX `index_users_username` ON `${TABLE_NAME}` (`username`)"
}
],
"foreignKeys": []
},
{
"tableName": "chatrooms",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` TEXT NOT NULL, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `open` INTEGER NOT NULL, `alert` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`ownerId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`lastMessageUserId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "subscriptionId",
"columnName": "subscriptionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "fullname",
"columnName": "fullname",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "ownerId",
"columnName": "ownerId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "readonly",
"columnName": "readonly",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "isDefault",
"columnName": "isDefault",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "favorite",
"columnName": "favorite",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "open",
"columnName": "open",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "alert",
"columnName": "alert",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "unread",
"columnName": "unread",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userMentions",
"columnName": "userMentions",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "groupMentions",
"columnName": "groupMentions",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "updatedAt",
"columnName": "updatedAt",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lastSeen",
"columnName": "lastSeen",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lastMessageText",
"columnName": "lastMessageText",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastMessageUserId",
"columnName": "lastMessageUserId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastMessageTimestamp",
"columnName": "lastMessageTimestamp",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "broadcast",
"columnName": "broadcast",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_chatrooms_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX `index_chatrooms_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_chatrooms_ownerId",
"unique": false,
"columnNames": [
"ownerId"
],
"createSql": "CREATE INDEX `index_chatrooms_ownerId` ON `${TABLE_NAME}` (`ownerId`)"
},
{
"name": "index_chatrooms_subscriptionId",
"unique": true,
"columnNames": [
"subscriptionId"
],
"createSql": "CREATE UNIQUE INDEX `index_chatrooms_subscriptionId` ON `${TABLE_NAME}` (`subscriptionId`)"
},
{
"name": "index_chatrooms_updatedAt",
"unique": false,
"columnNames": [
"updatedAt"
],
"createSql": "CREATE INDEX `index_chatrooms_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)"
},
{
"name": "index_chatrooms_lastMessageUserId",
"unique": false,
"columnNames": [
"lastMessageUserId"
],
"createSql": "CREATE INDEX `index_chatrooms_lastMessageUserId` ON `${TABLE_NAME}` (`lastMessageUserId`)"
}
],
"foreignKeys": [
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"ownerId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"lastMessageUserId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "messages",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `roomId` TEXT NOT NULL, `message` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `senderId` TEXT, `updatedAt` INTEGER, `editedAt` INTEGER, `editedBy` TEXT, `senderAlias` TEXT, `avatar` TEXT, `type` TEXT, `groupable` INTEGER NOT NULL, `parseUrls` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `role` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`senderId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`editedBy`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "roomId",
"columnName": "roomId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "message",
"columnName": "message",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "senderId",
"columnName": "senderId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "updatedAt",
"columnName": "updatedAt",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "editedAt",
"columnName": "editedAt",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "editedBy",
"columnName": "editedBy",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "senderAlias",
"columnName": "senderAlias",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "avatar",
"columnName": "avatar",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "groupable",
"columnName": "groupable",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "parseUrls",
"columnName": "parseUrls",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "pinned",
"columnName": "pinned",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "role",
"columnName": "role",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"senderId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"editedBy"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "message_favorites",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `userId` TEXT NOT NULL, PRIMARY KEY(`messageId`, `userId`), FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"messageId",
"userId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"messageId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "message_mentions",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `userId` TEXT NOT NULL, PRIMARY KEY(`messageId`, `userId`), FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"messageId",
"userId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"messageId"
],
"referencedColumns": [
"id"
]
},
{
"table": "users",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "message_channels",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `roomId` TEXT NOT NULL, `roomName` TEXT, PRIMARY KEY(`messageId`, `roomId`), FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "roomId",
"columnName": "roomId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "roomName",
"columnName": "roomName",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"messageId",
"roomId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"messageId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "attachments",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `message_id` TEXT NOT NULL, `title` TEXT, `type` TEXT, `description` TEXT, `text` TEXT, `author_name` TEXT, `author_icon` TEXT, `author_link` TEXT, `thumb_url` TEXT, `color` TEXT, `title_link` TEXT, `title_link_download` INTEGER NOT NULL, `image_url` TEXT, `image_type` TEXT, `image_size` INTEGER, `video_url` TEXT, `video_type` TEXT, `video_size` INTEGER, `audio_url` TEXT, `audio_type` TEXT, `audio_size` INTEGER, `message_link` TEXT, `timestamp` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`message_id`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "messageId",
"columnName": "message_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "text",
"columnName": "text",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "authorName",
"columnName": "author_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "authorIcon",
"columnName": "author_icon",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "authorLink",
"columnName": "author_link",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "thumbUrl",
"columnName": "thumb_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "titleLink",
"columnName": "title_link",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "titleLinkDownload",
"columnName": "title_link_download",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageUrl",
"columnName": "image_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "imageType",
"columnName": "image_type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "imageSize",
"columnName": "image_size",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "videoUrl",
"columnName": "video_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "videoType",
"columnName": "video_type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "videoSize",
"columnName": "video_size",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "audioUrl",
"columnName": "audio_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "audioType",
"columnName": "audio_type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "audioSize",
"columnName": "audio_size",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "messageLink",
"columnName": "message_link",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": [
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"message_id"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "attachment_fields",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `attachmentId` TEXT NOT NULL, `title` TEXT NOT NULL, `value` TEXT NOT NULL, FOREIGN KEY(`attachmentId`) REFERENCES `attachments`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "attachmentId",
"columnName": "attachmentId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": [
{
"table": "attachments",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"attachmentId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "urls",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `messageId` TEXT NOT NULL, `url` TEXT NOT NULL, `hostname` TEXT, `title` TEXT, `description` TEXT, `imageUrl` TEXT, FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "hostname",
"columnName": "hostname",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "imageUrl",
"columnName": "imageUrl",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_urls_messageId",
"unique": false,
"columnNames": [
"messageId"
],
"createSql": "CREATE INDEX `index_urls_messageId` ON `${TABLE_NAME}` (`messageId`)"
}
],
"foreignKeys": [
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"messageId"
],
"referencedColumns": [
"id"
]
}
]
},
{
"tableName": "reactions",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`reaction` TEXT NOT NULL, PRIMARY KEY(`reaction`))",
"fields": [
{
"fieldPath": "reaction",
"columnName": "reaction",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"reaction"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "reactions_message_relations",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `reactionId` TEXT NOT NULL, `messageId` TEXT NOT NULL, `count` INTEGER NOT NULL, FOREIGN KEY(`reactionId`) REFERENCES `reactions`(`reaction`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "reactionId",
"columnName": "reactionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "messageId",
"columnName": "messageId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "count",
"columnName": "count",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_reactions_message_relations_messageId",
"unique": false,
"columnNames": [
"messageId"
],
"createSql": "CREATE INDEX `index_reactions_message_relations_messageId` ON `${TABLE_NAME}` (`messageId`)"
}
],
"foreignKeys": [
{
"table": "reactions",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"reactionId"
],
"referencedColumns": [
"reaction"
]
},
{
"table": "messages",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"messageId"
],
"referencedColumns": [
"id"
]
}
]
}
],
"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, \"03aec453cb4faec2d1357fdb673b151e\")"
]
}
}
\ No newline at end of file
...@@ -39,20 +39,6 @@ class ChatRoomFragmentModule { ...@@ -39,20 +39,6 @@ class ChatRoomFragmentModule {
return CancelStrategy(owner, jobs) return CancelStrategy(owner, jobs)
} }
@Provides
@PerFragment
@Named("currentServer")
fun provideCurrentServer(currentServerInteractor: GetCurrentServerInteractor): String {
return currentServerInteractor.get()!!
}
@Provides
@PerFragment
fun provideDatabaseManager(factory: DatabaseManagerFactory,
@Named("currentServer") currentServer: String): DatabaseManager {
return factory.create(currentServer)
}
@Provides @Provides
@PerFragment @PerFragment
fun provideChatRoomDao(manager: DatabaseManager): ChatRoomDao = manager.chatRoomDao() fun provideChatRoomDao(manager: DatabaseManager): ChatRoomDao = manager.chatRoomDao()
......
...@@ -14,6 +14,7 @@ import chat.rocket.android.db.model.ReactionMessageRelation ...@@ -14,6 +14,7 @@ import chat.rocket.android.db.model.ReactionMessageRelation
import chat.rocket.android.db.model.UrlEntity import chat.rocket.android.db.model.UrlEntity
import chat.rocket.android.db.model.UserEntity import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.db.model.UserStatus import chat.rocket.android.db.model.UserStatus
import chat.rocket.android.db.model.asEntity
import chat.rocket.android.util.extensions.removeTrailingSlash import chat.rocket.android.util.extensions.removeTrailingSlash
import chat.rocket.android.util.extensions.toEntity import chat.rocket.android.util.extensions.toEntity
import chat.rocket.android.util.extensions.userId import chat.rocket.android.util.extensions.userId
...@@ -113,12 +114,23 @@ class DatabaseManager(val context: Application, ...@@ -113,12 +114,23 @@ class DatabaseManager(val context: Application,
Timber.d("Running ChatRooms transaction: remove: $toRemove - insert: $toInsert - update: $filteredUpdate") Timber.d("Running ChatRooms transaction: remove: $toRemove - insert: $toInsert - update: $filteredUpdate")
chatRoomDao().update(filteredInsert, filteredUpdate, toRemove.toList()) chatRoomDao().update(filteredInsert, filteredUpdate, toRemove.toList())
//updateMessages(batch)
} catch (ex: Exception) { } catch (ex: Exception) {
Timber.d(ex, "Error updating chatrooms") Timber.d(ex, "Error updating chatrooms")
} }
} }
} }
private fun updateMessages(batch: List<StreamMessage<BaseRoom>>) {
val list = batch.filterNot { it.type == Type.Removed }
.filter { it.data is Room }
.filterNot { (it.data as Room).lastMessage == null }
.map { (it.data as Room).lastMessage!! }
processMessagesBatch(list)
}
fun updateSelfUser(myself: Myself) { fun updateSelfUser(myself: Myself) {
launch(dbContext) { launch(dbContext) {
val user = userDao().getUser(myself.id) val user = userDao().getUser(myself.id)
...@@ -157,7 +169,7 @@ class DatabaseManager(val context: Application, ...@@ -157,7 +169,7 @@ class DatabaseManager(val context: Application,
private suspend fun createMessageEntities(message: Message): Pair<MessageEntity, List<BaseMessageEntity>> { private suspend fun createMessageEntities(message: Message): Pair<MessageEntity, List<BaseMessageEntity>> {
val messageEntity = message.toEntity() val messageEntity = message.toEntity()
val list = mutableListOf<BaseMessageEntity>() val list = mutableListOf<BaseMessageEntity>()
//createAttachments(message)?.let {} createAttachments(message)?.let { list.addAll(it) }
createFavoriteRelations(message)?.let { list.addAll(it) } createFavoriteRelations(message)?.let { list.addAll(it) }
createMentionRelations(message)?.let { list.addAll(it) } createMentionRelations(message)?.let { list.addAll(it) }
createChannelRelations(message)?.let { list.addAll(it) } createChannelRelations(message)?.let { list.addAll(it) }
...@@ -174,11 +186,13 @@ class DatabaseManager(val context: Application, ...@@ -174,11 +186,13 @@ class DatabaseManager(val context: Application,
return null return null
} }
val reactions = message.reactions!!
val list = mutableListOf<BaseMessageEntity>() val list = mutableListOf<BaseMessageEntity>()
message.reactions!!.keys.forEach { reaction -> reactions.keys.forEach { reaction ->
list.add(ReactionEntity(reaction)) list.add(ReactionEntity(reaction))
val users = message.reactions!![reaction] val users = reactions[reaction]
users?.size?.let { size -> users?.size?.let { size ->
list.add(ReactionMessageRelation(reaction, message.id, size)) list.add(ReactionMessageRelation(reaction, message.id, size))
} }
...@@ -247,10 +261,13 @@ class DatabaseManager(val context: Application, ...@@ -247,10 +261,13 @@ class DatabaseManager(val context: Application,
return null return null
} }
message.attachments!!.forEach { val list = ArrayList<BaseMessageEntity>(message.attachments!!.size)
message.attachments!!.forEach { attachment ->
list.addAll(attachment.asEntity(message.id))
} }
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
return list
} }
private suspend fun createUpdates(): List<ChatRoomEntity> { private suspend fun createUpdates(): List<ChatRoomEntity> {
......
...@@ -4,6 +4,15 @@ import androidx.room.ColumnInfo ...@@ -4,6 +4,15 @@ import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import chat.rocket.android.util.extension.orFalse
import chat.rocket.core.model.attachment.Attachment
import chat.rocket.core.model.attachment.AudioAttachment
import chat.rocket.core.model.attachment.AuthorAttachment
import chat.rocket.core.model.attachment.ColorAttachment
import chat.rocket.core.model.attachment.ImageAttachment
import chat.rocket.core.model.attachment.MessageAttachment
import chat.rocket.core.model.attachment.VideoAttachment
import timber.log.Timber
@Entity(tableName = "attachments", @Entity(tableName = "attachments",
foreignKeys = [ foreignKeys = [
...@@ -12,47 +21,47 @@ import androidx.room.PrimaryKey ...@@ -12,47 +21,47 @@ import androidx.room.PrimaryKey
]) ])
data class AttachmentEntity( data class AttachmentEntity(
@PrimaryKey @PrimaryKey
val id: String, var id: String,
@ColumnInfo(name = "message_id") @ColumnInfo(name = "message_id")
val messageId: String, val messageId: String,
val title: String?, val title: String? = null,
val type: String?, val type: String? = null,
val description: String?, val description: String? = null,
val text: String?, val text: String? = null,
@ColumnInfo(name = "author_name") @ColumnInfo(name = "author_name")
val authorName: String?, val authorName: String? = null,
@ColumnInfo(name = "author_icon") @ColumnInfo(name = "author_icon")
val authorIcon: String?, val authorIcon: String? = null,
@ColumnInfo(name = "author_link") @ColumnInfo(name = "author_link")
val authorLink: String?, val authorLink: String? = null,
@ColumnInfo(name = "thumb_url") @ColumnInfo(name = "thumb_url")
val thumbUrl: String?, val thumbUrl: String? = null,
val color: String?, val color: String? = null,
@ColumnInfo(name = "title_link") @ColumnInfo(name = "title_link")
val titleLink: String?, val titleLink: String? = null,
@ColumnInfo(name = "title_link_download") @ColumnInfo(name = "title_link_download")
val titleLinkDownload: String?, val titleLinkDownload: Boolean = false,
@ColumnInfo(name = "image_url") @ColumnInfo(name = "image_url")
val imageUrl: String?, val imageUrl: String? = null,
@ColumnInfo(name = "image_type") @ColumnInfo(name = "image_type")
val imageType: String?, val imageType: String? = null,
@ColumnInfo(name = "image_size") @ColumnInfo(name = "image_size")
val imageSize: String?, val imageSize: Long? = null,
@ColumnInfo(name = "video_url") @ColumnInfo(name = "video_url")
val videoUrl: String?, val videoUrl: String? = null,
@ColumnInfo(name = "video_type") @ColumnInfo(name = "video_type")
val videoType: String?, val videoType: String? = null,
@ColumnInfo(name = "video_size") @ColumnInfo(name = "video_size")
val videoSize: String?, val videoSize: Long? = null,
@ColumnInfo(name = "audio_url") @ColumnInfo(name = "audio_url")
val audioUrl: String?, val audioUrl: String? = null,
@ColumnInfo(name = "audio_type") @ColumnInfo(name = "audio_type")
val audioType: String?, val audioType: String? = null,
@ColumnInfo(name = "audio_size") @ColumnInfo(name = "audio_size")
val audioSize: String?, val audioSize: Long? = null,
@ColumnInfo(name = "message_link") @ColumnInfo(name = "message_link")
val messageLink: String?, val messageLink: String? = null,
val timestamp: Long? val timestamp: Long? = null
) : BaseMessageEntity ) : BaseMessageEntity
@Entity(tableName = "attachment_fields", @Entity(tableName = "attachment_fields",
...@@ -67,4 +76,106 @@ data class AttachmentFieldEntity( ...@@ -67,4 +76,106 @@ data class AttachmentFieldEntity(
) : BaseMessageEntity { ) : BaseMessageEntity {
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
var id: Long? = null var id: Long? = null
} }
\ No newline at end of file
fun Attachment.asEntity(msgId: String): List<BaseMessageEntity> {
return when(this) {
is ImageAttachment -> listOf(asEntity(msgId))
is VideoAttachment -> listOf(asEntity(msgId))
is AudioAttachment -> listOf(asEntity(msgId))
is AuthorAttachment -> asEntity(msgId)
is ColorAttachment -> listOf(asEntity(msgId))
is MessageAttachment -> listOf(asEntity(msgId))
// TODO - Action Attachments
else -> {
Timber.d("Missing conversion for: ${javaClass.canonicalName}")
emptyList()
}
}
}
fun ImageAttachment.asEntity(msgId: String): AttachmentEntity =
AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
title = title,
description = description,
text = text,
titleLink = titleLink,
titleLinkDownload = titleLinkDownload.orFalse(),
imageUrl = url,
imageType = type,
imageSize = size
)
fun VideoAttachment.asEntity(msgId: String): AttachmentEntity =
AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
title = title,
description = description,
text = text,
titleLink = titleLink,
titleLinkDownload = titleLinkDownload.orFalse(),
videoUrl = url,
videoType = type,
videoSize = size
)
fun AudioAttachment.asEntity(msgId: String): AttachmentEntity =
AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
title = title,
description = description,
text = text,
titleLink = titleLink,
titleLinkDownload = titleLinkDownload.orFalse(),
audioUrl = url,
audioType = type,
audioSize = size
)
fun AuthorAttachment.asEntity(msgId: String): List<BaseMessageEntity> {
val list = mutableListOf<BaseMessageEntity>()
val attachment = AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
authorLink = url,
authorIcon = authorIcon,
authorName = authorName
)
list.add(attachment)
fields?.forEach { field ->
val entity = AttachmentFieldEntity(
attachmentId = attachment.id,
title = field.title,
value = field.value
)
list.add(entity)
}
return list
}
fun ColorAttachment.asEntity(msgId: String): AttachmentEntity =
AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
color = color.rawColor
)
// TODO - how to model An message attachment with attachments???
fun MessageAttachment.asEntity(msgId: String): AttachmentEntity =
AttachmentEntity(
id = "${msgId}_${hashCode()}",
messageId = msgId,
authorName = author,
authorIcon = icon,
text = text,
thumbUrl = thumbUrl,
color = color?.rawColor,
messageLink = url,
timestamp = timestamp
)
\ No newline at end of file
...@@ -12,6 +12,7 @@ import chat.rocket.core.internal.realtime.socket.connect ...@@ -12,6 +12,7 @@ import chat.rocket.core.internal.realtime.socket.connect
import chat.rocket.core.internal.realtime.socket.disconnect import chat.rocket.core.internal.realtime.socket.disconnect
import chat.rocket.core.internal.realtime.socket.model.State import chat.rocket.core.internal.realtime.socket.model.State
import chat.rocket.core.internal.realtime.socket.model.StreamMessage import chat.rocket.core.internal.realtime.socket.model.StreamMessage
import chat.rocket.core.internal.realtime.socket.model.Type
import chat.rocket.core.internal.realtime.subscribeActiveUsers import chat.rocket.core.internal.realtime.subscribeActiveUsers
import chat.rocket.core.internal.realtime.subscribeRoomMessages import chat.rocket.core.internal.realtime.subscribeRoomMessages
import chat.rocket.core.internal.realtime.subscribeRooms import chat.rocket.core.internal.realtime.subscribeRooms
...@@ -129,9 +130,9 @@ class ConnectionManager( ...@@ -129,9 +130,9 @@ class ConnectionManager(
} }
val messagesActor = createBatchActor<Message>(messagesContext, parent = connectJob, val messagesActor = createBatchActor<Message>(messagesContext, parent = connectJob,
maxSize = 100, maxTime = 300) { messages -> maxSize = 100, maxTime = 500) { messages ->
Timber.d("Processing Messages batch: ${messages.size}") Timber.d("Processing Messages batch: ${messages.size}")
dbManager.processMessagesBatch(messages) dbManager.processMessagesBatch(messages.distinctBy { it.id })
} }
// stream-notify-user - ${userId}/rooms-changed // stream-notify-user - ${userId}/rooms-changed
...@@ -139,6 +140,11 @@ class ConnectionManager( ...@@ -139,6 +140,11 @@ class ConnectionManager(
for (room in client.roomsChannel) { for (room in client.roomsChannel) {
Timber.d("GOT Room streamed") Timber.d("GOT Room streamed")
roomsActor.send(room) roomsActor.send(room)
if (room.type != Type.Removed) {
room.data.lastMessage?.let {
messagesActor.send(it)
}
}
} }
} }
......
...@@ -9,7 +9,7 @@ import kotlinx.coroutines.experimental.launch ...@@ -9,7 +9,7 @@ import kotlinx.coroutines.experimental.launch
inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit): Job? { inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit): Job? {
// Checking first for activity and view saves us from some synchronyzed and thread local checks // Checking first for activity and view saves us from some synchronyzed and thread local checks
if (activity != null && view != null) { if (activity != null && view != null && context != null) {
// If we already are running on the Main Thread (UI Thread), just go ahead and execute the block // If we already are running on the Main Thread (UI Thread), just go ahead and execute the block
return if (Looper.getMainLooper() == Looper.myLooper()) { return if (Looper.getMainLooper() == Looper.myLooper()) {
block(activity!!) block(activity!!)
...@@ -17,7 +17,7 @@ inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit): ...@@ -17,7 +17,7 @@ inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit):
} else { } else {
// Launch a Job on the UI context and check again if the activity and view are still valid // Launch a Job on the UI context and check again if the activity and view are still valid
launch(UI) { launch(UI) {
if (activity != null && view != null) { if (activity != null && view != null && context != null) {
block(activity!!) block(activity!!)
} }
} }
......
...@@ -4,12 +4,10 @@ import chat.rocket.android.db.model.MessageEntity ...@@ -4,12 +4,10 @@ import chat.rocket.android.db.model.MessageEntity
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.registerPushToken import chat.rocket.core.internal.rest.registerPushToken
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
import chat.rocket.core.model.asString import chat.rocket.core.model.asString
import kotlinx.coroutines.experimental.CommonPool import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
import timber.log.Timber import timber.log.Timber
......
package chat.rocket.android.util.extension
fun Boolean?.orFalse(): Boolean = this ?: false
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment