diff --git a/README.md b/README.md
index 9100752170..12cb75fc5a 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,16 @@

-# Rocket.Chat Android native application
+# IMPORTANT: PLEASE READ THIS FIRST
+
+Rocket.Chat mobile is [moving to React Native](https://rocket.chat/2019/10/11/moving-mobile-apps-to-react/). Development on this repository by Rocket.Chat has now ceased. If your team is interested in taking over and maintaining this Android native client repository then please [contact us](https://rocket.chat/contact).
+
+# Legacy Rocket.Chat Android native application
[](https://circleci.com/gh/RocketChat/Rocket.Chat.Android/tree/develop) [](https://www.codacy.com/app/matheusjardimb/Rocket.Chat.Android)
## Get it from the stores
-[](https://play.google.com/store/apps/details?id=chat.rocket.android) [](https://f-droid.org/en/packages/chat.rocket.android/)
+[](https://f-droid.org/en/packages/chat.rocket.android/)
## Description
diff --git a/app/build.gradle b/app/build.gradle
index 9bfe286740..fa95dbac5f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -18,8 +18,8 @@ android {
applicationId "chat.rocket.android"
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
- versionCode 2077
- versionName "3.5.1"
+ versionCode 2080
+ versionName "3.5.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
diff --git a/app/schemas/chat.rocket.android.db.RCDatabase/14.json b/app/schemas/chat.rocket.android.db.RCDatabase/14.json
new file mode 100644
index 0000000000..12f96013a2
--- /dev/null
+++ b/app/schemas/chat.rocket.android.db.RCDatabase/14.json
@@ -0,0 +1,1117 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 14,
+ "identityHash": "c7462d4b4f9ad32f9d8d2e53a7abd535",
+ "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, `parentId` TEXT, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `topic` TEXT, `announcement` TEXT, `description` TEXT, `open` INTEGER, `alert` INTEGER, `unread` INTEGER, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, 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": "parentId",
+ "columnName": "parentId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "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": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "announcement",
+ "columnName": "announcement",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "open",
+ "columnName": "open",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "alert",
+ "columnName": "alert",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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
+ },
+ {
+ "fieldPath": "muted",
+ "columnName": "muted",
+ "affinity": "TEXT",
+ "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, `synced` INTEGER NOT NULL, `unread` INTEGER, 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
+ },
+ {
+ "fieldPath": "synced",
+ "columnName": "synced",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "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, `fallback` 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, `has_actions` INTEGER NOT NULL, `has_fields` INTEGER NOT NULL, `button_alignment` TEXT, 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": "fallback",
+ "columnName": "fallback",
+ "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
+ },
+ {
+ "fieldPath": "hasActions",
+ "columnName": "has_actions",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasFields",
+ "columnName": "has_fields",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "buttonAlignment",
+ "columnName": "button_alignment",
+ "affinity": "TEXT",
+ "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": [
+ {
+ "name": "index_attachment_fields_attachmentId",
+ "unique": false,
+ "columnNames": [
+ "attachmentId"
+ ],
+ "createSql": "CREATE INDEX `index_attachment_fields_attachmentId` ON `${TABLE_NAME}` (`attachmentId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "attachments",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "attachmentId"
+ ],
+ "referencedColumns": [
+ "_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "attachment_action",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `attachmentId` TEXT NOT NULL, `type` TEXT NOT NULL, `text` TEXT, `url` TEXT, `isWebView` INTEGER, `webViewHeightRatio` TEXT, `imageUrl` TEXT, `message` TEXT, `isMessageInChatWindow` INTEGER, 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": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "text",
+ "columnName": "text",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isWebView",
+ "columnName": "isWebView",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "webViewHeightRatio",
+ "columnName": "webViewHeightRatio",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "imageUrl",
+ "columnName": "imageUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "message",
+ "columnName": "message",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isMessageInChatWindow",
+ "columnName": "isMessageInChatWindow",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_attachment_action_attachmentId",
+ "unique": false,
+ "columnNames": [
+ "attachmentId"
+ ],
+ "createSql": "CREATE INDEX `index_attachment_action_attachmentId` ON `${TABLE_NAME}` (`attachmentId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "attachments",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "attachmentId"
+ ],
+ "referencedColumns": [
+ "_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "urls",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`urlId` 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": "urlId",
+ "columnName": "urlId",
+ "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": [
+ "urlId"
+ ],
+ "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, `messageId` TEXT NOT NULL, `count` INTEGER NOT NULL, `usernames` TEXT NOT NULL, `names` TEXT NOT NULL, PRIMARY KEY(`reaction`), FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "reaction",
+ "columnName": "reaction",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "messageId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "count",
+ "columnName": "count",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "usernames",
+ "columnName": "usernames",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "names",
+ "columnName": "names",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "reaction"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [
+ {
+ "name": "index_reactions_messageId",
+ "unique": false,
+ "columnNames": [
+ "messageId"
+ ],
+ "createSql": "CREATE INDEX `index_reactions_messageId` ON `${TABLE_NAME}` (`messageId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "messages",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "messageId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "messages_sync",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`roomId` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`roomId`))",
+ "fields": [
+ {
+ "fieldPath": "roomId",
+ "columnName": "roomId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "roomId"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "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, \"c7462d4b4f9ad32f9d8d2e53a7abd535\")"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/schemas/chat.rocket.android.db.RCDatabase/15.json b/app/schemas/chat.rocket.android.db.RCDatabase/15.json
new file mode 100644
index 0000000000..95eed60122
--- /dev/null
+++ b/app/schemas/chat.rocket.android.db.RCDatabase/15.json
@@ -0,0 +1,1117 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 15,
+ "identityHash": "c7462d4b4f9ad32f9d8d2e53a7abd535",
+ "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, `parentId` TEXT, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `topic` TEXT, `announcement` TEXT, `description` TEXT, `open` INTEGER, `alert` INTEGER, `unread` INTEGER, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, 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": "parentId",
+ "columnName": "parentId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "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": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "announcement",
+ "columnName": "announcement",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "open",
+ "columnName": "open",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "alert",
+ "columnName": "alert",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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
+ },
+ {
+ "fieldPath": "muted",
+ "columnName": "muted",
+ "affinity": "TEXT",
+ "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, `synced` INTEGER NOT NULL, `unread` INTEGER, 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
+ },
+ {
+ "fieldPath": "synced",
+ "columnName": "synced",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "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, `fallback` 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, `has_actions` INTEGER NOT NULL, `has_fields` INTEGER NOT NULL, `button_alignment` TEXT, 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": "fallback",
+ "columnName": "fallback",
+ "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
+ },
+ {
+ "fieldPath": "hasActions",
+ "columnName": "has_actions",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasFields",
+ "columnName": "has_fields",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "buttonAlignment",
+ "columnName": "button_alignment",
+ "affinity": "TEXT",
+ "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": [
+ {
+ "name": "index_attachment_fields_attachmentId",
+ "unique": false,
+ "columnNames": [
+ "attachmentId"
+ ],
+ "createSql": "CREATE INDEX `index_attachment_fields_attachmentId` ON `${TABLE_NAME}` (`attachmentId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "attachments",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "attachmentId"
+ ],
+ "referencedColumns": [
+ "_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "attachment_action",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `attachmentId` TEXT NOT NULL, `type` TEXT NOT NULL, `text` TEXT, `url` TEXT, `isWebView` INTEGER, `webViewHeightRatio` TEXT, `imageUrl` TEXT, `message` TEXT, `isMessageInChatWindow` INTEGER, 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": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "text",
+ "columnName": "text",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isWebView",
+ "columnName": "isWebView",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "webViewHeightRatio",
+ "columnName": "webViewHeightRatio",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "imageUrl",
+ "columnName": "imageUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "message",
+ "columnName": "message",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isMessageInChatWindow",
+ "columnName": "isMessageInChatWindow",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_attachment_action_attachmentId",
+ "unique": false,
+ "columnNames": [
+ "attachmentId"
+ ],
+ "createSql": "CREATE INDEX `index_attachment_action_attachmentId` ON `${TABLE_NAME}` (`attachmentId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "attachments",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "attachmentId"
+ ],
+ "referencedColumns": [
+ "_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "urls",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`urlId` 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": "urlId",
+ "columnName": "urlId",
+ "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": [
+ "urlId"
+ ],
+ "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, `messageId` TEXT NOT NULL, `count` INTEGER NOT NULL, `usernames` TEXT NOT NULL, `names` TEXT NOT NULL, PRIMARY KEY(`reaction`), FOREIGN KEY(`messageId`) REFERENCES `messages`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "reaction",
+ "columnName": "reaction",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "messageId",
+ "columnName": "messageId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "count",
+ "columnName": "count",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "usernames",
+ "columnName": "usernames",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "names",
+ "columnName": "names",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "reaction"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [
+ {
+ "name": "index_reactions_messageId",
+ "unique": false,
+ "columnNames": [
+ "messageId"
+ ],
+ "createSql": "CREATE INDEX `index_reactions_messageId` ON `${TABLE_NAME}` (`messageId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "messages",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "messageId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "messages_sync",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`roomId` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`roomId`))",
+ "fields": [
+ {
+ "fieldPath": "roomId",
+ "columnName": "roomId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "roomId"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "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, \"c7462d4b4f9ad32f9d8d2e53a7abd535\")"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/foss/java/chat/rocket/android/dynamiclinks/DynamicLinksForFirebase.kt b/app/src/foss/java/chat/rocket/android/dynamiclinks/DynamicLinksForFirebase.kt
index a78c0da247..276530af8e 100644
--- a/app/src/foss/java/chat/rocket/android/dynamiclinks/DynamicLinksForFirebase.kt
+++ b/app/src/foss/java/chat/rocket/android/dynamiclinks/DynamicLinksForFirebase.kt
@@ -7,11 +7,15 @@ import javax.inject.Inject
class DynamicLinksForFirebase @Inject constructor(private val context: Context) : DynamicLinks {
- override fun getDynamicLink(intent: Intent, deepLinkCallback: (Uri?) -> Unit? ) {
+ override fun getDynamicLink(intent: Intent, deepLinkCallback: (Uri?) -> Unit?) {
deepLinkCallback(null)
}
- override fun createDynamicLink(username: String?, server: String, deepLinkCallback: (String?) -> Unit?) {
+ override fun createDynamicLink(
+ username: String,
+ server: String,
+ deepLinkCallback: (String?) -> Unit?
+ ) {
deepLinkCallback(null)
}
}
diff --git a/app/src/foss/java/chat/rocket/android/push/PushToken.kt b/app/src/foss/java/chat/rocket/android/push/PushToken.kt
index e65dbfd23c..6768b826d3 100644
--- a/app/src/foss/java/chat/rocket/android/push/PushToken.kt
+++ b/app/src/foss/java/chat/rocket/android/push/PushToken.kt
@@ -1,4 +1,14 @@
package chat.rocket.android.push
-fun refreshPushToken() {
+import chat.rocket.core.RocketChatClient
+
+fun retrieveCurrentPushNotificationToken(
+ rocketChatClient: RocketChatClient,
+ shouldUnregister: Boolean = false
+) {
+ // Do nothing
}
+
+fun registerPushNotificationToken(rocketChatClient: RocketChatClient, token: String) {
+ // Do nothing
+}
\ No newline at end of file
diff --git a/app/src/foss/java/chat/rocket/android/util/GMSManager.kt b/app/src/foss/java/chat/rocket/android/util/FCMManager.kt
similarity index 58%
rename from app/src/foss/java/chat/rocket/android/util/GMSManager.kt
rename to app/src/foss/java/chat/rocket/android/util/FCMManager.kt
index 8346171417..16f7dd8677 100644
--- a/app/src/foss/java/chat/rocket/android/util/GMSManager.kt
+++ b/app/src/foss/java/chat/rocket/android/util/FCMManager.kt
@@ -1,5 +1,5 @@
package chat.rocket.android.util
-fun invalidateFirebaseToken(token: String) {
+fun invalidateFirebaseToken() {
//Do absolutely nothing
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4aad7ac636..793d1472df 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -109,15 +109,6 @@
android:name=".settings.password.ui.PasswordActivity"
android:theme="@style/AppTheme" />
-
-
-
-
-
-
"
+ override fun activityInjector() = activityDispatchingAndroidInjector
- if (currentServer == "") {
- val message = "null currentServer"
- Timber.d(IllegalStateException(message), message)
- }
+ override fun serviceInjector() = serviceDispatchingAndroidInjector
- val settings = settingsInteractor.get(currentServer)
- if (settings.isEmpty()) {
- val message = "Empty settings for: $currentServer"
- Timber.d(IllegalStateException(message), message)
- }
- val baseUrl = settings[SITE_URL]
- if (baseUrl == null) {
- val message = "Server $currentServer SITE_URL"
- Timber.d(IllegalStateException(message), message)
- }
- }
+ override fun broadcastReceiverInjector() = broadcastReceiverInjector
+
+ override fun workerInjector() = workerInjector
- private fun setupFresco() {
- Fresco.initialize(this, imagePipelineConfig, draweeConfig)
+ companion object {
+ var context: WeakReference? = null
}
+ private fun setupFresco() = Fresco.initialize(this, imagePipelineConfig, draweeConfig)
+
private fun setupTimber() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
@@ -151,20 +128,6 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
}
}
- override fun activityInjector() = activityDispatchingAndroidInjector
-
- override fun serviceInjector() = serviceDispatchingAndroidInjector
-
- override fun broadcastReceiverInjector() = broadcastReceiverInjector
-
- override fun workerInjector() = workerInjector
-
- companion object {
- var context: WeakReference? = null
- fun getAppContext(): Context? {
- return context?.get()
- }
- }
// TODO - FIXME - This is a big Workaround
/**
@@ -173,28 +136,32 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
*/
fun loadEmojis() {
EmojiRepository.init(this)
- val currentServer = getCurrentServerInteractor.get()
- currentServer?.let { server ->
- GlobalScope.launch {
- val client = factory.get(server)
+ runBlocking {
+ getCurrentServerInteractor.get()?.let { server ->
EmojiRepository.setCurrentServerUrl(server)
+ val customEmojis = retryIO("getCustomEmojis()") {
+ factory.get(server).getCustomEmojis().update
+ }
val customEmojiList = mutableListOf()
try {
- for (customEmoji in retryIO("getCustomEmojis()") { client.getCustomEmojis() }) {
- customEmojiList.add(Emoji(
- shortname = ":${customEmoji.name}:",
- category = EmojiCategory.CUSTOM.name,
- url = "$currentServer/emoji-custom/${customEmoji.name}.${customEmoji.extension}",
- count = 0,
- fitzpatrick = Fitzpatrick.Default.type,
- keywords = customEmoji.aliases,
- shortnameAlternates = customEmoji.aliases,
- siblings = mutableListOf(),
- unicode = "",
- isDefault = true
- ))
+ if (customEmojis != null) {
+ for (customEmoji in customEmojis) {
+ customEmojiList.add(
+ Emoji(
+ shortname = ":${customEmoji.name}:",
+ category = EmojiCategory.CUSTOM.name,
+ url = "$server/emoji-custom/${customEmoji.name}.${customEmoji.extension}",
+ count = 0,
+ fitzpatrick = Fitzpatrick.Default.type,
+ keywords = customEmoji.aliases,
+ shortnameAlternates = customEmoji.aliases,
+ siblings = mutableListOf(),
+ unicode = "",
+ isDefault = true
+ )
+ )
+ }
}
-
EmojiRepository.load(this@RocketChatApplication, customEmojis = customEmojiList)
} catch (ex: RocketChatException) {
Timber.e(ex)
@@ -204,8 +171,3 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
}
}
}
-
-private fun LocalRepository.needOldMessagesCleanUp() = getBoolean(CLEANUP_OLD_MESSAGES_NEEDED, true)
-private fun LocalRepository.setOldMessagesCleanedUp() = save(CLEANUP_OLD_MESSAGES_NEEDED, false)
-
-private const val CLEANUP_OLD_MESSAGES_NEEDED = "CLEANUP_OLD_MESSAGES_NEEDED"
diff --git a/app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt b/app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt
index 2dc436a27f..da73919453 100644
--- a/app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt
@@ -19,7 +19,7 @@ class AuthenticationModule {
@Provides
@PerActivity
- fun provideJob() = Job()
+ fun provideJob(): Job = Job()
@Provides
@PerActivity
diff --git a/app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
index 3d2c8ecdf8..d06b52ef2b 100644
--- a/app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
@@ -144,15 +144,16 @@ class LoginPresenter @Inject constructor(
}
val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(
- settings.siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- username,
- thumb,
- token?.userId,
- token?.authToken
+ serverName = settings.siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = username,
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
+
saveAccountInteractor.save(account)
}
diff --git a/app/src/main/java/chat/rocket/android/authentication/loginoptions/presentation/LoginOptionsPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/loginoptions/presentation/LoginOptionsPresenter.kt
index 06d4e6fcb4..a6373c68fa 100644
--- a/app/src/main/java/chat/rocket/android/authentication/loginoptions/presentation/LoginOptionsPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/loginoptions/presentation/LoginOptionsPresenter.kt
@@ -185,14 +185,14 @@ class LoginOptionsPresenter @Inject constructor(
}
val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(
- settings.siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- username,
- thumb,
- token?.userId,
- token?.authToken
+ serverName = settings.siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = username,
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
saveAccountInteractor.save(account)
}
diff --git a/app/src/main/java/chat/rocket/android/authentication/onboarding/presentation/OnBoardingPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/onboarding/presentation/OnBoardingPresenter.kt
index a059971d43..37979843ad 100644
--- a/app/src/main/java/chat/rocket/android/authentication/onboarding/presentation/OnBoardingPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/onboarding/presentation/OnBoardingPresenter.kt
@@ -13,7 +13,6 @@ import chat.rocket.android.util.extension.launchUI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject
-import javax.inject.Named
class OnBoardingPresenter @Inject constructor(
private val view: OnBoardingView,
@@ -23,12 +22,10 @@ class OnBoardingPresenter @Inject constructor(
refreshSettingsInteractor: RefreshSettingsInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
val settingsInteractor: GetSettingsInteractor,
- val factory: RocketChatClientFactory,
- @Named("currentServer") private val currentServer: String?
+ val factory: RocketChatClientFactory
) : CheckServerPresenter(
strategy = strategy,
factory = factory,
- currentSavedServer = currentServer,
settingsInteractor = settingsInteractor,
refreshSettingsInteractor = refreshSettingsInteractor
) {
diff --git a/app/src/main/java/chat/rocket/android/authentication/registerusername/presentation/RegisterUsernamePresenter.kt b/app/src/main/java/chat/rocket/android/authentication/registerusername/presentation/RegisterUsernamePresenter.kt
index a39790f5c6..56106b2bbc 100644
--- a/app/src/main/java/chat/rocket/android/authentication/registerusername/presentation/RegisterUsernamePresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/registerusername/presentation/RegisterUsernamePresenter.kt
@@ -83,14 +83,14 @@ class RegisterUsernamePresenter @Inject constructor(
}
val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(
- settings.siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- username,
- thumb,
- token?.userId,
- token?.authToken
+ serverName = settings.siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = username,
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
saveAccountInteractor.save(account)
}
diff --git a/app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
index 95c166595a..bc3ddc7b97 100644
--- a/app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
@@ -15,7 +15,6 @@ import chat.rocket.android.util.extensions.isValidUrl
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject
-import javax.inject.Named
class ServerPresenter @Inject constructor(
private val view: ServerView,
@@ -25,12 +24,10 @@ class ServerPresenter @Inject constructor(
private val refreshSettingsInteractor: RefreshSettingsInteractor,
private val getAccountsInteractor: GetAccountsInteractor,
val settingsInteractor: GetSettingsInteractor,
- val factory: RocketChatClientFactory,
- @Named("currentServer") private val currentServer: String?
+ val factory: RocketChatClientFactory
) : CheckServerPresenter(
strategy = strategy,
factory = factory,
- currentSavedServer = currentServer,
settingsInteractor = settingsInteractor,
versionCheckView = view,
refreshSettingsInteractor = refreshSettingsInteractor
diff --git a/app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt b/app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt
index eb8668ac58..32833d3c99 100644
--- a/app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt
@@ -236,13 +236,13 @@ class ServerFragment : Fragment(), ServerView {
override fun updateServerUrl(url: HttpUrl) {
ui {
- if (url.scheme() == "https") {
+ if (url.scheme == "https") {
spinner_server_protocol.setSelection(0)
} else {
spinner_server_protocol.setSelection(1)
}
- protocol = "${url.scheme()}://"
+ protocol = "${url.scheme}://"
text_server_url.textContent = url.toString().removePrefix(protocol)
}
}
diff --git a/app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt
index 3c0d9014e1..702c4da511 100644
--- a/app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt
@@ -104,14 +104,14 @@ class SignupPresenter @Inject constructor(
}
val thumb = currentServer.avatarUrl(me.username!!, token?.userId, token?.authToken)
val account = Account(
- settings.siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- me.username!!,
- thumb,
- token?.userId,
- token?.authToken
+ serverName = settings.siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = me.username!!,
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
saveAccountInteractor.save(account)
}
diff --git a/app/src/main/java/chat/rocket/android/authentication/twofactor/presentation/TwoFAPresenter.kt b/app/src/main/java/chat/rocket/android/authentication/twofactor/presentation/TwoFAPresenter.kt
index 107f12eb03..72d9eaa948 100644
--- a/app/src/main/java/chat/rocket/android/authentication/twofactor/presentation/TwoFAPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/authentication/twofactor/presentation/TwoFAPresenter.kt
@@ -105,14 +105,14 @@ class TwoFAPresenter @Inject constructor(
}
val thumb = currentServer.avatarUrl(me.username!!, token?.userId, token?.authToken)
val account = Account(
- settings.siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- me.username!!,
- thumb,
- token?.userId,
- token?.authToken
+ serverName = settings.siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = me.username!!,
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
saveAccountInteractor.save(account)
}
diff --git a/app/src/main/java/chat/rocket/android/chatinformation/di/MessageInfoFragmentModule.kt b/app/src/main/java/chat/rocket/android/chatinformation/di/MessageInfoFragmentModule.kt
index bb5e55eb0c..0a7c8d784d 100644
--- a/app/src/main/java/chat/rocket/android/chatinformation/di/MessageInfoFragmentModule.kt
+++ b/app/src/main/java/chat/rocket/android/chatinformation/di/MessageInfoFragmentModule.kt
@@ -14,7 +14,7 @@ class MessageInfoFragmentModule {
@Provides
@PerFragment
- fun provideJob() = Job()
+ fun provideJob(): Job = Job()
@Provides
@PerFragment
diff --git a/app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt b/app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt
index a013430044..84a27d4540 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt
@@ -18,7 +18,7 @@ class ChatRoomModule {
@Provides
@PerActivity
- fun provideJob() = Job()
+ fun provideJob(): Job = Job()
@Provides
@PerActivity
diff --git a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt
index 96b1d39b9f..6beb72f056 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt
@@ -37,7 +37,7 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
chatRoomType: String,
isReadOnly: Boolean,
chatRoomLastSeen: Long,
- isSubscribed: Boolean,
+ isSubscribed: Boolean?,
isCreator: Boolean,
isFavorite: Boolean
) {
@@ -127,7 +127,7 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
chatRoomType: String,
isChatRoomReadOnly: Boolean,
chatRoomLastSeen: Long,
- isChatRoomSubscribed: Boolean,
+ isChatRoomSubscribed: Boolean?,
isChatRoomCreator: Boolean,
isChatRoomFavorite: Boolean,
chatRoomMessage: String
diff --git a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
index 1b65510aa3..759d9b24fb 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
@@ -954,7 +954,7 @@ class ChatRoomPresenter @Inject constructor(
it.type is RoomType.DirectMessage || it.type is RoomType.LiveChat
}
.map { chatRoom ->
- val name = chatRoom.name
+ val name = chatRoom.name ?: ""
val fullName = chatRoom.fullName ?: ""
ChatRoomSuggestionUiModel(
text = name,
diff --git a/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt b/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
index 2af6fb6f95..59d8cc41b9 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
@@ -25,9 +25,9 @@ fun Context.chatRoomIntent(
chatRoomId: String,
chatRoomName: String,
chatRoomType: String,
- isReadOnly: Boolean,
+ isReadOnly: Boolean?,
chatRoomLastSeen: Long,
- isSubscribed: Boolean = true,
+ isSubscribed: Boolean? = true,
isCreator: Boolean = false,
isFavorite: Boolean = false,
chatRoomMessage: String? = null
diff --git a/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt b/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
index 72f123b008..911c5d341c 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
@@ -474,12 +474,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override fun sendMessage(text: String) {
ui {
if (!text.isBlank()) {
- if (text.startsWith("/")) {
- presenter.runCommand(text, chatRoomId)
- } else if (text.startsWith("+")) {
- presenter.reactToLastMessage(text, chatRoomId)
- } else {
- presenter.sendMessage(chatRoomId, text, editingMessageId)
+ when {
+ text.startsWith("/") -> presenter.runCommand(text, chatRoomId)
+ text.startsWith("+") -> presenter.reactToLastMessage(text, chatRoomId)
+ else -> presenter.sendMessage(chatRoomId, text, editingMessageId)
}
}
}
@@ -932,7 +930,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_send.setOnClickListener {
text_message.textContent.run {
if(this.isNotBlank()) {
- sendMessage(citation ?: "" + this)
+ sendMessage((citation ?: "") + this)
}
}
}
diff --git a/app/src/main/java/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt b/app/src/main/java/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt
index cfd01ed5a3..f4cbe9c8ea 100644
--- a/app/src/main/java/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt
+++ b/app/src/main/java/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt
@@ -47,6 +47,7 @@ import chat.rocket.core.model.url.Url
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import java.security.InvalidParameterException
import java.util.*
import java.util.Collections.emptyList
@@ -415,9 +416,9 @@ class UiModelMapper @Inject constructor(
title?.let { return it }
url.filterNotNull().forEach {
- val fileUrl = HttpUrl.parse(it)
+ val fileUrl = it.toHttpUrlOrNull()
fileUrl?.let { httpUrl ->
- return httpUrl.pathSegments().last()
+ return httpUrl.pathSegments.last()
}
}
@@ -429,7 +430,7 @@ class UiModelMapper @Inject constructor(
if (url.startsWith("http")) return url
val fullUrl = "$baseUrl$url"
- val httpUrl = HttpUrl.parse(fullUrl)
+ val httpUrl = fullUrl.toHttpUrlOrNull()
httpUrl?.let {
return it.newBuilder().apply {
addQueryParameter("rc_uid", token?.userId)
diff --git a/app/src/main/java/chat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt b/app/src/main/java/chat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt
index 739f4adbc6..ba3431a181 100644
--- a/app/src/main/java/chat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt
+++ b/app/src/main/java/chat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt
@@ -14,12 +14,14 @@ import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.date
+import chat.rocket.android.util.extensions.isGreaterThan
import chat.rocket.android.util.extensions.isNotNullNorEmpty
import chat.rocket.android.util.extensions.localDateTime
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.User
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.model.userStatusOf
+import chat.rocket.common.util.ifNull
import chat.rocket.core.model.Room
import chat.rocket.core.model.SpotlightResult
import ru.noties.markwon.Markwon
@@ -101,7 +103,7 @@ class RoomUiModelMapper(
RoomUiModel(
id = id,
name = name!!,
- type = type,
+ type = type!!,
avatar = serverUrl.avatarUrl(name!!, token?.userId, token?.authToken, isGroupOrChannel = true),
lastMessage = if (showLastMessage) {
mapLastMessage(
@@ -121,7 +123,7 @@ class RoomUiModelMapper(
fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel =
with(chatRoom.chatRoom) {
- val isUnread = alert || unread > 0
+ val isUnread = alert == true || unread.isGreaterThan(0)
val type = roomTypeOf(type)
val status = chatRoom.status?.let { userStatusOf(it) }
val roomName = mapName(name, fullname)
@@ -133,7 +135,7 @@ class RoomUiModelMapper(
} else {
serverUrl.avatarUrl(name, token?.userId, token?.authToken, isGroupOrChannel = true)
}
- val unread = mapUnread(unread)
+ val unread = unread?.let { mapUnread(it) }
val lastMessage = if (showLastMessage) {
mapLastMessage(
lastMessageUserId,
@@ -146,7 +148,6 @@ class RoomUiModelMapper(
null
}
val hasMentions = mapMentions(userMentions, groupMentions)
- val open = open
val lastMessageMarkdown =
lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
diff --git a/app/src/main/java/chat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt b/app/src/main/java/chat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt
index 4b536b3d4f..236f46847f 100644
--- a/app/src/main/java/chat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt
+++ b/app/src/main/java/chat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt
@@ -9,7 +9,7 @@ data class RoomUiModel(
val type: RoomType,
val name: CharSequence,
val avatar: String,
- val open: Boolean = false,
+ val open: Boolean? = false,
val date: CharSequence? = null,
val unread: String? = null,
val alert: Boolean = false,
diff --git a/app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt b/app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
index a5041928b8..48d97e409f 100644
--- a/app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
@@ -128,7 +128,7 @@ class ChatRoomsPresenter @Inject constructor(
if (myself?.username == null) {
view.showMessage(R.string.msg_generic_error)
} else {
- val id = if (isDirectMessage && !open) {
+ val id = if (isDirectMessage && open == false) {
// If from local database, we already have the roomId, no need to concatenate
if (local) {
retryIO {
diff --git a/app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt b/app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
index d9e1b1afaf..c45d576d1d 100644
--- a/app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
+++ b/app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
@@ -17,6 +17,7 @@ import chat.rocket.android.authentication.infrastructure.SharedPreferencesTokenR
import chat.rocket.android.chatroom.service.MessageService
import chat.rocket.android.dagger.qualifier.ForAuthentication
import chat.rocket.android.dagger.qualifier.ForMessages
+import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.dynamiclinks.DynamicLinksForFirebase
@@ -52,6 +53,7 @@ import chat.rocket.android.server.infrastructure.DatabaseMessagesRepository
import chat.rocket.android.server.infrastructure.JobSchedulerInteractorImpl
import chat.rocket.android.server.infrastructure.MemoryChatRoomsRepository
import chat.rocket.android.server.infrastructure.MemoryUsersRepository
+import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.infrastructure.SharedPreferencesAccountsRepository
import chat.rocket.android.server.infrastructure.SharedPreferencesPermissionsRepository
import chat.rocket.android.server.infrastructure.SharedPreferencesSettingsRepository
@@ -70,6 +72,7 @@ import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.NoOpLogger
import chat.rocket.common.util.PlatformLogger
+import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter
import com.facebook.drawee.backends.pipeline.DraweeConfig
@@ -342,7 +345,9 @@ class AppModule {
manager: NotificationManager,
moshi: Moshi,
getAccountInteractor: GetAccountInteractor,
- getSettingsInteractor: GetSettingsInteractor
+ getSettingsInteractor: GetSettingsInteractor,
+ currentServerInteractor: GetCurrentServerInteractor,
+ factory: RocketChatClientFactory
): PushManager {
return PushManager(
groupedPushes,
@@ -350,7 +355,9 @@ class AppModule {
moshi,
getAccountInteractor,
getSettingsInteractor,
- context
+ context,
+ currentServerInteractor,
+ factory
)
}
diff --git a/app/src/main/java/chat/rocket/android/dagger/module/ReceiverBuilder.kt b/app/src/main/java/chat/rocket/android/dagger/module/ReceiverBuilder.kt
index 9c35f8fd3f..e39d82fb97 100644
--- a/app/src/main/java/chat/rocket/android/dagger/module/ReceiverBuilder.kt
+++ b/app/src/main/java/chat/rocket/android/dagger/module/ReceiverBuilder.kt
@@ -1,8 +1,6 @@
package chat.rocket.android.dagger.module
import chat.rocket.android.push.DeleteReceiver
-import chat.rocket.android.push.DirectReplyReceiver
-import chat.rocket.android.push.DirectReplyReceiverProvider
import chat.rocket.android.push.di.DeleteReceiverProvider
import dagger.Module
import dagger.android.ContributesAndroidInjector
@@ -12,7 +10,4 @@ abstract class ReceiverBuilder {
@ContributesAndroidInjector(modules = [DeleteReceiverProvider::class])
abstract fun bindDeleteReceiver(): DeleteReceiver
-
- @ContributesAndroidInjector(modules = [DirectReplyReceiverProvider::class])
- abstract fun bindDirectReplyReceiver(): DirectReplyReceiver
}
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/db/DatabaseManager.kt b/app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
index 055904d770..2185f455ac 100644
--- a/app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
+++ b/app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
@@ -19,7 +19,6 @@ import chat.rocket.android.db.model.asEntity
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.exhaustive
import chat.rocket.android.util.extensions.removeTrailingSlash
-import chat.rocket.android.util.extensions.toEntity
import chat.rocket.android.util.extensions.userId
import chat.rocket.android.util.retryDB
import chat.rocket.common.model.BaseRoom
@@ -35,6 +34,7 @@ import chat.rocket.core.model.LastMessage
import chat.rocket.core.model.Message
import chat.rocket.core.model.Myself
import chat.rocket.core.model.Room
+import chat.rocket.core.model.asString
import chat.rocket.core.model.userId
import com.facebook.drawee.backends.pipeline.Fresco
import kotlinx.coroutines.GlobalScope
@@ -94,7 +94,7 @@ class DatabaseManager(val context: Application, val serverUrl: String, val token
}
suspend fun sendOperation(operation: Operation) {
- Timber.d("writerChannel: $writeChannel, closedForSend: ${writeChannel.isClosedForSend}, closedForReceive: ${writeChannel.isClosedForReceive}, empty: ${writeChannel.isEmpty}, full: ${writeChannel.isFull}")
+ Timber.d("writerChannel: $writeChannel, closedForSend: ${writeChannel.isClosedForSend}, closedForReceive: ${writeChannel.isClosedForReceive}, empty: ${writeChannel.isEmpty}")
writeChannel.send(operation)
}
@@ -229,7 +229,25 @@ class DatabaseManager(val context: Application, val serverUrl: String, val token
}
private suspend fun createMessageEntities(message: Message): Pair> {
- val messageEntity = message.toEntity()
+ val messageEntity = MessageEntity(
+ id = message.id,
+ roomId = message.roomId,
+ message = message.message,
+ timestamp = message.timestamp,
+ senderId = message.sender?.id,
+ updatedAt = message.updatedAt,
+ editedAt = message.editedAt,
+ editedBy = message.editedBy?.id,
+ senderAlias = message.senderAlias,
+ avatar = message.avatar,
+ type = message.type.asString(),
+ groupable = message.groupable,
+ parseUrls = message.parseUrls,
+ pinned = message.pinned,
+ role = message.role,
+ synced = message.synced
+ )
+
val list = mutableListOf()
createAttachments(message)?.let { list.addAll(it) }
createFavoriteRelations(message)?.let { list.addAll(it) }
@@ -534,7 +552,7 @@ class DatabaseManager(val context: Application, val serverUrl: String, val token
subscriptionId = subscriptionId,
parentId = parentId,
type = type.toString(),
- name = name,
+ name = name.toString(),
fullname = fullName,
userId = userId,
ownerId = user?.id,
diff --git a/app/src/main/java/chat/rocket/android/db/RCDatabase.kt b/app/src/main/java/chat/rocket/android/db/RCDatabase.kt
index 78178a34a6..2e177f94aa 100644
--- a/app/src/main/java/chat/rocket/android/db/RCDatabase.kt
+++ b/app/src/main/java/chat/rocket/android/db/RCDatabase.kt
@@ -32,7 +32,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter
ReactionEntity::class,
MessagesSync::class
],
- version = 13,
+ version = 15,
exportSchema = true
)
@TypeConverters(StringListConverter::class)
diff --git a/app/src/main/java/chat/rocket/android/db/model/ChatRoomEntity.kt b/app/src/main/java/chat/rocket/android/db/model/ChatRoomEntity.kt
index e709003705..5185f168ad 100644
--- a/app/src/main/java/chat/rocket/android/db/model/ChatRoomEntity.kt
+++ b/app/src/main/java/chat/rocket/android/db/model/ChatRoomEntity.kt
@@ -38,9 +38,9 @@ data class ChatRoomEntity(
var topic: String? = null,
var announcement: String? = null,
var description: String? = null,
- var open: Boolean = true,
- var alert: Boolean = false,
- var unread: Long = 0,
+ var open: Boolean? = true,
+ var alert: Boolean? = false,
+ var unread: Long? = 0,
var userMentions: Long? = 0,
var groupMentions: Long? = 0,
var updatedAt: Long? = -1,
diff --git a/app/src/main/java/chat/rocket/android/dynamiclinks/DynamicLinks.kt b/app/src/main/java/chat/rocket/android/dynamiclinks/DynamicLinks.kt
index 582ea8d993..2576c663c3 100644
--- a/app/src/main/java/chat/rocket/android/dynamiclinks/DynamicLinks.kt
+++ b/app/src/main/java/chat/rocket/android/dynamiclinks/DynamicLinks.kt
@@ -7,5 +7,5 @@ interface DynamicLinks {
fun getDynamicLink(intent: Intent, deepLinkCallback: (Uri?) -> Unit? )
- fun createDynamicLink(username: String?, server: String, deepLinkCallback: (String?) -> Unit?)
+ fun createDynamicLink(username: String, server: String, deepLinkCallback: (String?) -> Unit?)
}
diff --git a/app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt b/app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt
index 2e178db56e..1340a1c781 100644
--- a/app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt
+++ b/app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt
@@ -22,7 +22,6 @@ interface LocalRepository {
fun getLastChatroomsRefresh(url: String): Long
companion object {
- const val KEY_PUSH_TOKEN = "KEY_PUSH_TOKEN"
const val TOKEN_KEY = "token_"
const val SETTINGS_KEY = "settings_"
const val PERMISSIONS_KEY = "permissions_"
@@ -32,7 +31,4 @@ interface LocalRepository {
const val LAST_CHATROOMS_REFRESH = "_chatrooms_refresh"
}
}
-
-// FIXME - we are saving the user full name here when the server is UI_Use_Real_Name true
-fun LocalRepository.checkIfMyself(username: String) = username() == username
fun LocalRepository.username() = get(LocalRepository.CURRENT_USERNAME_KEY)
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/main/di/MainModule.kt b/app/src/main/java/chat/rocket/android/main/di/MainModule.kt
index ab8819e171..ae65a1b1b5 100644
--- a/app/src/main/java/chat/rocket/android/main/di/MainModule.kt
+++ b/app/src/main/java/chat/rocket/android/main/di/MainModule.kt
@@ -25,7 +25,7 @@ class MainModule {
@Provides
@PerActivity
- fun provideJob() = Job()
+ fun provideJob(): Job = Job()
@Provides
fun provideLifecycleOwner(activity: MainActivity): LifecycleOwner = activity
diff --git a/app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt b/app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt
index 983f55bd28..f6044a9467 100644
--- a/app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt
+++ b/app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt
@@ -70,9 +70,9 @@ class MainNavigator(internal val activity: MainActivity) {
chatRoomId: String,
chatRoomName: String,
chatRoomType: String,
- isReadOnly: Boolean,
+ isReadOnly: Boolean?,
chatRoomLastSeen: Long,
- isSubscribed: Boolean,
+ isSubscribed: Boolean?,
isCreator: Boolean,
isFavorite: Boolean
) {
diff --git a/app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt b/app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt
index a7df0cba77..1fb2093117 100644
--- a/app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt
@@ -2,11 +2,24 @@ package chat.rocket.android.main.presentation
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.core.behaviours.AppLanguageView
+import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.UserHelper
import chat.rocket.android.push.GroupedPush
-import chat.rocket.android.server.domain.*
+import chat.rocket.android.push.retrieveCurrentPushNotificationToken
+import chat.rocket.android.server.domain.GetCurrentLanguageInteractor
+import chat.rocket.android.server.domain.GetSettingsInteractor
+import chat.rocket.android.server.domain.RefreshPermissionsInteractor
+import chat.rocket.android.server.domain.RefreshSettingsInteractor
+import chat.rocket.android.server.domain.RemoveAccountInteractor
+import chat.rocket.android.server.domain.SaveAccountInteractor
+import chat.rocket.android.server.domain.TokenRepository
+import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account
+import chat.rocket.android.server.domain.siteName
+import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
+import chat.rocket.android.server.infrastructure.RocketChatClientFactory
+import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.serverLogoUrl
import javax.inject.Inject
@@ -14,6 +27,7 @@ import javax.inject.Named
class MainPresenter @Inject constructor(
@Named("currentServer") private val currentServer: String?,
+ private val strategy: CancelStrategy,
private val mainNavigator: MainNavigator,
private val appLanguageView: AppLanguageView,
private val refreshSettingsInteractor: RefreshSettingsInteractor,
@@ -25,7 +39,8 @@ class MainPresenter @Inject constructor(
private val tokenRepository: TokenRepository,
private val userHelper: UserHelper,
private val saveAccountInteractor: SaveAccountInteractor,
- private val removeAccountInteractor: RemoveAccountInteractor
+ private val removeAccountInteractor: RemoveAccountInteractor,
+ private val factory: RocketChatClientFactory
) {
fun connect() = currentServer?.let {
@@ -36,15 +51,11 @@ class MainPresenter @Inject constructor(
fun clearNotificationsForChatRoom(chatRoomId: String?) {
if (chatRoomId == null) return
-
groupedPush.hostToPushMessageList[currentServer].let { list ->
list?.removeAll { it.info.roomId == chatRoomId }
}
}
- fun showChatList(chatRoomId: String? = null, deepLinkInfo: DeepLinkInfo? = null) =
- mainNavigator.toChatList(chatRoomId, deepLinkInfo)
-
fun getAppLanguage() {
with(getLanguageInteractor) {
getLanguage()?.let { language ->
@@ -74,17 +85,25 @@ class MainPresenter @Inject constructor(
)
val account = Account(
- siteName() ?: currentServer,
- currentServer,
- icon,
- logo,
- userHelper.username() ?: "",
- thumb,
- token?.userId,
- token?.authToken
+ serverName = siteName() ?: currentServer,
+ serverUrl = currentServer,
+ serverLogoUrl = icon,
+ serverBackgroundImageUrl = logo,
+ userName = userHelper.username() ?: "",
+ userAvatarUrl = thumb,
+ authToken = token?.authToken,
+ userId = token?.userId
)
+
saveAccountInteractor.save(account)
}
}
}
+
+ fun registerPushNotificationToken() = launchUI(strategy) {
+ currentServer?.let { retrieveCurrentPushNotificationToken(factory.get(it)) }
+ }
+
+ fun showChatList(chatRoomId: String? = null, deepLinkInfo: DeepLinkInfo? = null) =
+ mainNavigator.toChatList(chatRoomId, deepLinkInfo)
}
diff --git a/app/src/main/java/chat/rocket/android/main/ui/MainActivity.kt b/app/src/main/java/chat/rocket/android/main/ui/MainActivity.kt
index 66390b8ed0..8bb58df162 100644
--- a/app/src/main/java/chat/rocket/android/main/ui/MainActivity.kt
+++ b/app/src/main/java/chat/rocket/android/main/ui/MainActivity.kt
@@ -16,8 +16,8 @@ import chat.rocket.android.chatrooms.ui.ChatRoomsFragment
import chat.rocket.android.chatrooms.ui.TAG_CHAT_ROOMS_FRAGMENT
import chat.rocket.android.core.behaviours.AppLanguageView
import chat.rocket.android.main.presentation.MainPresenter
-import chat.rocket.android.push.refreshPushToken
import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID
+import chat.rocket.android.authentication.domain.model.DEEP_LINK_INFO_KEY
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
@@ -40,15 +40,14 @@ class MainActivity : AppCompatActivity(), HasActivityInjector,
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- refreshPushToken()
- deepLinkInfo =
- intent.getParcelableExtra(chat.rocket.android.authentication.domain.model.DEEP_LINK_INFO_KEY)
+ deepLinkInfo = intent.getParcelableExtra(DEEP_LINK_INFO_KEY)
with(presenter) {
connect()
getAppLanguage()
removeOldAccount()
saveNewAccount()
+ registerPushNotificationToken()
intent.getStringExtra(INTENT_CHAT_ROOM_ID).let {
clearNotificationsForChatRoom(it)
showChatList(it, deepLinkInfo)
@@ -58,9 +57,7 @@ class MainActivity : AppCompatActivity(), HasActivityInjector,
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
- intent?.getParcelableExtra(
- chat.rocket.android.authentication.domain.model.DEEP_LINK_INFO_KEY
- )?.let { deepLinkInfo ->
+ intent?.getParcelableExtra(DEEP_LINK_INFO_KEY)?.let { deepLinkInfo ->
(supportFragmentManager.findFragmentByTag(TAG_CHAT_ROOMS_FRAGMENT) as? ChatRoomsFragment)
?.processDeepLink(deepLinkInfo)
}
diff --git a/app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt b/app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
index 3c4f561246..ba28ea9e1c 100644
--- a/app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
+++ b/app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
@@ -5,22 +5,17 @@ import android.net.Uri
import chat.rocket.android.chatroom.domain.UriInteractor
import chat.rocket.android.core.behaviours.showMessage
import chat.rocket.android.core.lifecycle.CancelStrategy
-import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.helper.UserHelper
import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.GetCurrentServerInteractor
-import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.TokenRepository
-import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infrastructure.RocketChatClientFactory
-import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extension.compressImageAndGetByteArray
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.UserStatus
-import chat.rocket.common.model.userStatusOf
import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.realtime.setDefaultStatus
@@ -38,24 +33,9 @@ class ProfilePresenter @Inject constructor(
private val navigator: MainNavigator,
private val uriInteractor: UriInteractor,
val userHelper: UserHelper,
- @Named("currentServer") private val currentServer: String?,
serverInteractor: GetCurrentServerInteractor,
factory: RocketChatClientFactory,
- removeAccountInteractor: RemoveAccountInteractor,
- tokenRepository: TokenRepository,
- dbManagerFactory: DatabaseManagerFactory?,
- managerFactory: ConnectionManagerFactory
-) : CheckServerPresenter(
- strategy = strategy,
- factory = factory,
- currentSavedServer = currentServer,
- serverInteractor = serverInteractor,
- removeAccountInteractor = removeAccountInteractor,
- tokenRepository = tokenRepository,
- dbManagerFactory = dbManagerFactory,
- managerFactory = managerFactory,
- tokenView = view,
- navigator = navigator
+ tokenRepository: TokenRepository
) {
private val serverUrl = serverInteractor.get()!!
private val client: RocketChatClient = factory.get(serverUrl)
@@ -66,7 +46,7 @@ class ProfilePresenter @Inject constructor(
launchUI(strategy) {
view.showLoading()
try {
- val me = retryIO(description = "serverInfo", times = 5) {
+ val me = retryIO(description = "me", times = 5) {
client.me()
}
diff --git a/app/src/main/java/chat/rocket/android/profile/presentation/ProfileView.kt b/app/src/main/java/chat/rocket/android/profile/presentation/ProfileView.kt
index 2c905810c6..1463964229 100644
--- a/app/src/main/java/chat/rocket/android/profile/presentation/ProfileView.kt
+++ b/app/src/main/java/chat/rocket/android/profile/presentation/ProfileView.kt
@@ -2,9 +2,8 @@ package chat.rocket.android.profile.presentation
import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView
-import chat.rocket.android.server.presentation.TokenView
-interface ProfileView : TokenView, LoadingView, MessageView {
+interface ProfileView : LoadingView, MessageView {
/**
* Shows the user profile.
diff --git a/app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt b/app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
index 86525d8277..14f263a1b9 100644
--- a/app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
+++ b/app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
@@ -35,7 +35,6 @@ import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
-import chat.rocket.android.util.invalidateFirebaseToken
import chat.rocket.common.model.UserStatus
import chat.rocket.common.model.userStatusOf
import com.facebook.drawee.backends.pipeline.Fresco
@@ -46,8 +45,6 @@ import io.reactivex.rxkotlin.Observables
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.avatar_profile.*
import kotlinx.android.synthetic.main.fragment_profile.*
-import kotlinx.android.synthetic.main.fragment_profile.view_dim
-import kotlinx.android.synthetic.main.fragment_profile.view_loading
import kotlinx.android.synthetic.main.update_avatar_options.*
import javax.inject.Inject
@@ -149,15 +146,17 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
image_avatar?.setImageURI(avatarUrl)
}
- override fun onProfileUpdatedSuccessfully(updatedEmail: String, updatedName: String, updatedUserName: String) {
+ override fun onProfileUpdatedSuccessfully(
+ updatedEmail: String,
+ updatedName: String,
+ updatedUserName: String
+ ) {
currentEmail = updatedEmail
currentName = updatedName
currentUsername = updatedUserName
showMessage(getString(R.string.msg_profile_updated_successfully))
}
- override fun invalidateToken(token: String) = invalidateFirebaseToken(token)
-
override fun showLoading() {
enableUserInput(false)
ui { view_loading.isVisible = true }
diff --git a/app/src/main/java/chat/rocket/android/push/DirectReplyReceiver.kt b/app/src/main/java/chat/rocket/android/push/DirectReplyReceiver.kt
deleted file mode 100644
index 00c4f694b0..0000000000
--- a/app/src/main/java/chat/rocket/android/push/DirectReplyReceiver.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-package chat.rocket.android.push
-
-import android.app.NotificationManager
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.widget.Toast
-import androidx.core.app.RemoteInput
-import chat.rocket.android.R
-import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
-import chat.rocket.common.RocketChatException
-import chat.rocket.core.internal.rest.sendMessage
-import dagger.android.AndroidInjection
-import kotlinx.coroutines.MainScope
-import kotlinx.coroutines.launch
-import timber.log.Timber
-import java.util.*
-import javax.inject.Inject
-
-/**
- * BroadcastReceiver for direct reply on notifications.
- */
-class DirectReplyReceiver : BroadcastReceiver() {
- @Inject lateinit var factory: ConnectionManagerFactory
- @Inject lateinit var groupedPushes: GroupedPush
- @Inject lateinit var pushManager: PushManager
- @Inject lateinit var manager: NotificationManager
-
- override fun onReceive(context: Context, intent: Intent) {
- AndroidInjection.inject(this, context)
- if (ACTION_REPLY == intent.action) {
- val message = intent.getParcelableExtra(EXTRA_PUSH_MESSAGE)
- message?.let {
- MainScope().launch {
- val notificationId = it.notificationId.toInt()
- val hostname = it.info.host
- try {
- sendMessage(it, extractReplyMessage(intent))
- clearNotificationsByHostAndNotificationId(hostname, notificationId)
- manager.cancel(notificationId)
- val feedback = context.getString(R.string.notif_success_sending, it.title)
- Toast.makeText(context, feedback, Toast.LENGTH_SHORT).show()
- } catch (ex: RocketChatException) {
- Timber.e(ex)
- val feedback = context.getString(R.string.notif_error_sending)
- Toast.makeText(context, feedback, Toast.LENGTH_SHORT).show()
- clearNotificationsByHostAndNotificationId(hostname, notificationId)
- pushManager.showNotification(it)
- }
- }
- }
- }
- }
-
- private suspend fun sendMessage(message: PushMessage, replyText: CharSequence?) {
- replyText?.let { reply ->
- val currentServer = message.info.hostname
- val roomId = message.info.roomId
- val connectionManager = factory.create(currentServer)
- val client = connectionManager?.client
- val id = UUID.randomUUID().toString()
- client?.sendMessage(id, roomId, reply.toString())
- // Do we need to disconnect here?
- }
- }
-
- private fun extractReplyMessage(intent: Intent): CharSequence? {
- val bundle = RemoteInput.getResultsFromIntent(intent)
- if (bundle != null) {
- return bundle.getCharSequence(REMOTE_INPUT_REPLY)
- }
- return null
- }
-
- /**
- * Clear notifications by the host they belong to and its unique id.
- */
- private fun clearNotificationsByHostAndNotificationId(host: String, notificationId: Int) {
- if (groupedPushes.hostToPushMessageList.isNotEmpty()) {
- val notifications = groupedPushes.hostToPushMessageList[host]
- notifications?.let {
- notifications.removeAll {
- it.notificationId.toInt() == notificationId
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/push/DirectReplyReceiverProvider.kt b/app/src/main/java/chat/rocket/android/push/DirectReplyReceiverProvider.kt
deleted file mode 100644
index 28a201fc08..0000000000
--- a/app/src/main/java/chat/rocket/android/push/DirectReplyReceiverProvider.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package chat.rocket.android.push
-
-import chat.rocket.android.dagger.module.AppModule
-import dagger.Module
-import dagger.android.ContributesAndroidInjector
-
-@Module
-abstract class DirectReplyReceiverProvider {
- @ContributesAndroidInjector(modules = [AppModule::class])
- abstract fun provideDirectReplyReceiver(): DirectReplyReceiver
-}
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/push/GroupedPush.kt b/app/src/main/java/chat/rocket/android/push/GroupedPush.kt
index d52f381292..cd4a1225a3 100644
--- a/app/src/main/java/chat/rocket/android/push/GroupedPush.kt
+++ b/app/src/main/java/chat/rocket/android/push/GroupedPush.kt
@@ -1,7 +1,6 @@
package chat.rocket.android.push
import java.util.concurrent.atomic.AtomicInteger
-import javax.inject.Singleton
typealias TupleGroupIdMessageCount = Pair
diff --git a/app/src/main/java/chat/rocket/android/push/PushInfo.kt b/app/src/main/java/chat/rocket/android/push/PushInfo.kt
new file mode 100644
index 0000000000..5622052b44
--- /dev/null
+++ b/app/src/main/java/chat/rocket/android/push/PushInfo.kt
@@ -0,0 +1,29 @@
+package chat.rocket.android.push
+
+import chat.rocket.common.model.RoomType
+import com.squareup.moshi.Json
+import se.ansman.kotshi.JsonSerializable
+
+@JsonSerializable
+data class PushInfo constructor(
+ @Json(name = "host") val hostname: String,
+ @Json(name = "rid") val roomId: String,
+ val type: RoomType,
+ val name: String?,
+ val sender: PushSender?
+) {
+ val createdAt: Long
+ get() = System.currentTimeMillis()
+ val host by lazy {
+ sanitizeUrl(hostname)
+ }
+
+ private fun sanitizeUrl(baseUrl: String): String {
+ var url = baseUrl.trim()
+ while (url.endsWith('/')) {
+ url = url.dropLast(1)
+ }
+
+ return url
+ }
+}
diff --git a/app/src/main/java/chat/rocket/android/push/PushManager.kt b/app/src/main/java/chat/rocket/android/push/PushManager.kt
index efd3b84e6c..74b3568dff 100644
--- a/app/src/main/java/chat/rocket/android/push/PushManager.kt
+++ b/app/src/main/java/chat/rocket/android/push/PushManager.kt
@@ -10,29 +10,27 @@ import android.content.Intent
import android.media.RingtoneManager
import android.os.Build
import android.os.Bundle
-import android.os.Parcel
-import android.os.Parcelable
import android.text.Html
import android.text.Spanned
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
-import androidx.core.app.RemoteInput
import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
import chat.rocket.android.R
-import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.server.domain.GetAccountInteractor
+import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.siteName
+import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
-import com.squareup.moshi.Json
import com.squareup.moshi.Moshi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
-import se.ansman.kotshi.JsonSerializable
-import se.ansman.kotshi.KotshiConstructor
import timber.log.Timber
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
@@ -40,20 +38,26 @@ import javax.inject.Inject
class PushManager @Inject constructor(
private val groupedPushes: GroupedPush,
- private val manager: NotificationManager,
+ private val notificationManager: NotificationManager,
private val moshi: Moshi,
private val getAccountInteractor: GetAccountInteractor,
private val getSettingsInteractor: GetSettingsInteractor,
- private val context: Context
+ private val context: Context,
+ private val serverInteractor: GetCurrentServerInteractor,
+ private val factory: RocketChatClientFactory
) {
-
private val random = Random()
+ fun registerPushNotificationToken(token: String) = GlobalScope.launch(Dispatchers.IO) {
+ serverInteractor.get()?.let { currentServer ->
+ registerPushNotificationToken(factory.get(currentServer), token)
+ }
+ }
+
/**
* Handles a receiving push by creating and displaying an appropriate notification based
* on the *data* param bundle received.
*/
- @Synchronized
fun handle(data: Bundle) = runBlocking {
val message = data["message"] as String?
val ejson = data["ejson"] as String?
@@ -65,64 +69,76 @@ class PushManager @Inject constructor(
val count = data["count"] as String?
try {
- val adapter = moshi.adapter(PushInfo::class.java)
-
- val pushMessage = if (ejson != null) {
- val info = adapter.fromJson(ejson)
- PushMessage(title!!, message!!, info!!, image, count, notId, summaryText, style)
- } else {
- PushMessage(title!!, message!!, PushInfo.EMPTY, image, count, notId, summaryText, style)
+ if (title != null && message != null) {
+ val pushInfo = if (ejson != null) {
+ moshi.adapter(PushInfo::class.java).fromJson(ejson)
+ } else {
+ null
+ }
+ val pushMessage = PushMessage(
+ title = title,
+ message = message,
+ info = pushInfo ?: PushInfo(
+ hostname = "",
+ roomId = "",
+ type = roomTypeOf(RoomType.CHANNEL),
+ name = "",
+ sender = null
+ ),
+ image = image,
+ count = count,
+ notificationId = notId,
+ summaryText = summaryText,
+ style = style
+ )
+ showNotification(pushMessage)
+ Timber.d("Received push message: $pushMessage")
}
-
- Timber.d("Received push message: $pushMessage")
-
- showNotification(pushMessage)
} catch (ex: Exception) {
- Timber.e(ex, "Error parsing PUSH message: $data")
- ex.printStackTrace()
+ Timber.e(ex, "Error parsing push message: $data")
}
}
@SuppressLint("NewApi")
- suspend fun showNotification(pushMessage: PushMessage) {
+ fun showNotification(pushMessage: PushMessage) {
val notId = pushMessage.notificationId.toInt()
val host = pushMessage.info.host
- if (!hasAccount(host)) {
- createSingleNotification(pushMessage)?.let {
- NotificationManagerCompat.from(context).notify(notId, it)
+ createSingleNotification(pushMessage)?.let { notification ->
+ NotificationManagerCompat.from(context).notify(notId, notification)
+ if (!hasAccount(host)) {
+ Timber.d("Test or generic Push message: $pushMessage sent")
+ return
}
- Timber.d("ignoring push message: $pushMessage (maybe a test notification?)")
- return
}
- val groupTuple = getGroupForHost(host)
+ val groupTuple = getGroupForHost(host)
groupTuple.second.incrementAndGet()
- val notIdListForHostname: MutableList? = groupedPushes.hostToPushMessageList[host]
+ val notIdListForHostname: MutableList? =
+ groupedPushes.hostToPushMessageList[host]
if (notIdListForHostname == null) {
groupedPushes.hostToPushMessageList[host] = arrayListOf(pushMessage)
} else {
notIdListForHostname.add(0, pushMessage)
}
- val notification = createSingleNotification(pushMessage)
val pushMessageList = groupedPushes.hostToPushMessageList[host]
-
- notification?.let {
- manager.notify(notId, it)
- }
-
pushMessageList?.let {
if (pushMessageList.size > 1) {
val groupNotification = createGroupNotification(pushMessage)
groupNotification?.let {
- NotificationManagerCompat.from(context).notify(groupTuple.first, groupNotification)
+ NotificationManagerCompat.from(context)
+ .notify(groupTuple.first, groupNotification)
}
}
}
}
+ private fun hasAccount(host: String): Boolean {
+ return getAccountInteractor.get(host) != null
+ }
+
private fun getGroupForHost(host: String): TupleGroupIdMessageCount {
val size = groupedPushes.groupMap.size
var group = groupedPushes.groupMap[host]
@@ -133,10 +149,6 @@ class PushManager @Inject constructor(
return group
}
- private suspend fun hasAccount(host: String): Boolean {
- return getAccountInteractor.get(host) != null
- }
-
@SuppressLint("NewApi")
@RequiresApi(Build.VERSION_CODES.N)
private fun createGroupNotification(pushMessage: PushMessage): Notification? {
@@ -183,11 +195,10 @@ class PushManager @Inject constructor(
with(pushMessage) {
val host = info.host
- val builder = createBaseNotificationBuilder(pushMessage)
- .setGroupSummary(false)
+ val builder = createBaseNotificationBuilder(pushMessage).setGroupSummary(false)
if (style == null || "inbox" == style) {
- val pushMessageList = groupedPushes.hostToPushMessageList.get(host)
+ val pushMessageList = groupedPushes.hostToPushMessageList[host]
if (pushMessageList != null) {
val userMessages = pushMessageList.filter {
@@ -221,17 +232,19 @@ class PushManager @Inject constructor(
return builder.build()
}
} else {
- val bigTextStyle = NotificationCompat.BigTextStyle()
- .bigText(message.fromHtml())
+ val bigTextStyle = NotificationCompat.BigTextStyle().bigText(message.fromHtml())
builder.setStyle(bigTextStyle)
}
- return builder.addReplyAction(pushMessage).build()
+ return builder.build()
}
}
@RequiresApi(Build.VERSION_CODES.O)
- private fun createBaseNotificationBuilder(pushMessage: PushMessage, grouped: Boolean = false): NotificationCompat.Builder {
+ private fun createBaseNotificationBuilder(
+ pushMessage: PushMessage,
+ grouped: Boolean = false
+ ): NotificationCompat.Builder {
return with(pushMessage) {
val id = notificationId.toInt()
val host = info.host
@@ -261,12 +274,13 @@ class PushManager @Inject constructor(
channelName = host
channelId = host
}
- val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
+ val channel =
+ NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
channel.enableLights(false)
channel.enableVibration(true)
channel.setShowBadge(true)
- manager.createNotificationChannel(channel)
+ notificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}
@@ -293,13 +307,29 @@ class PushManager @Inject constructor(
val deleteIntent = Intent(context, DeleteReceiver::class.java)
.putExtra(EXTRA_NOT_ID, pushMessage.notificationId.toInt())
.putExtra(EXTRA_HOSTNAME, pushMessage.info.host)
- return PendingIntent.getBroadcast(context, pushMessage.notificationId.toInt(), deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
+ return PendingIntent.getBroadcast(
+ context,
+ pushMessage.notificationId.toInt(),
+ deleteIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ )
}
- private fun getContentIntent(context: Context, notificationId: Int, pushMessage: PushMessage, grouped: Boolean = false): PendingIntent {
+ private fun getContentIntent(
+ context: Context,
+ notificationId: Int,
+ pushMessage: PushMessage,
+ grouped: Boolean = false
+ ): PendingIntent {
val roomId = if (!grouped) pushMessage.info.roomId else null
- val notificationIntent = context.changeServerIntent(pushMessage.info.host, chatRoomId = roomId)
- return PendingIntent.getActivity(context, random.nextInt(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)
+ val notificationIntent =
+ context.changeServerIntent(pushMessage.info.host, chatRoomId = roomId)
+ return PendingIntent.getActivity(
+ context,
+ random.nextInt(),
+ notificationIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ )
}
// CharSequence extensions
@@ -311,59 +341,12 @@ class PushManager @Inject constructor(
}
}
- // NotificationCompat.Builder extensions
- private fun NotificationCompat.Builder.addReplyAction(pushMessage: PushMessage): NotificationCompat.Builder {
- val replyTextHint = context.getText(R.string.notif_action_reply_hint)
- val replyRemoteInput = RemoteInput.Builder(REMOTE_INPUT_REPLY)
- .setLabel(replyTextHint)
- .build()
- val pendingIntent = getReplyPendingIntent(pushMessage)
- val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_action_message_reply_24dp, replyTextHint, pendingIntent)
- .addRemoteInput(replyRemoteInput)
- .setAllowGeneratedReplies(true)
- .build()
-
- this.addAction(replyAction)
- return this
- }
-
- private fun getReplyIntent(pushMessage: PushMessage): Intent {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- Intent(context, DirectReplyReceiver::class.java)
- } else {
- Intent(context, MainActivity::class.java).also {
- it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
- }.also {
- it.action = ACTION_REPLY
- it.putExtra(EXTRA_PUSH_MESSAGE, pushMessage)
- }
- }
-
- private fun getReplyPendingIntent(pushMessage: PushMessage): PendingIntent {
- val replyIntent = getReplyIntent(pushMessage)
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- PendingIntent.getBroadcast(
- context,
- random.nextInt(),
- replyIntent,
- PendingIntent.FLAG_UPDATE_CURRENT
- )
- } else {
- PendingIntent.getActivity(
- context,
- random.nextInt(),
- replyIntent,
- PendingIntent.FLAG_UPDATE_CURRENT
- )
- }
- }
-
private fun NotificationCompat.Builder.setMessageNotification(): NotificationCompat.Builder {
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val res = context.resources
val smallIcon = res.getIdentifier(
- "rocket_chat_notification", "drawable", context.packageName)
+ "rocket_chat_notification", "drawable", context.packageName
+ )
with(this) {
setAutoCancel(true)
setShowWhen(true)
@@ -376,144 +359,5 @@ class PushManager @Inject constructor(
}
}
-data class PushMessage(
- val title: String,
- val message: String,
- val info: PushInfo,
- val image: String? = null,
- val count: String? = null,
- val notificationId: String,
- val summaryText: String? = null,
- val style: String? = null
-) : Parcelable {
-
- constructor(parcel: Parcel) : this(
- parcel.readString().orEmpty(),
- parcel.readString().orEmpty(),
- parcel.readParcelable(PushMessage::class.java.classLoader) ?: PushInfo.EMPTY,
- parcel.readString(),
- parcel.readString(),
- parcel.readString().orEmpty(),
- parcel.readString(),
- parcel.readString())
-
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeString(title)
- parcel.writeString(message)
- parcel.writeParcelable(info, flags)
- parcel.writeString(image)
- parcel.writeString(count)
- parcel.writeString(notificationId)
- parcel.writeString(summaryText)
- parcel.writeString(style)
- }
-
- override fun describeContents(): Int {
- return 0
- }
-
- companion object CREATOR : Parcelable.Creator {
- override fun createFromParcel(parcel: Parcel): PushMessage {
- return PushMessage(parcel)
- }
-
- override fun newArray(size: Int): Array {
- return arrayOfNulls(size)
- }
- }
-}
-
-@JsonSerializable
-data class PushInfo @KotshiConstructor constructor(
- @Json(name = "host") val hostname: String,
- @Json(name = "rid") val roomId: String,
- val type: RoomType,
- val name: String?,
- val sender: PushSender?
-) : Parcelable {
- val createdAt: Long
- get() = System.currentTimeMillis()
- val host by lazy {
- sanitizeUrl(hostname)
- }
-
- constructor(parcel: Parcel) : this(
- parcel.readString().orEmpty(),
- parcel.readString().orEmpty(),
- roomTypeOf(parcel.readString().orEmpty()),
- parcel.readString(),
- parcel.readParcelable(PushInfo::class.java.classLoader))
-
- private fun sanitizeUrl(baseUrl: String): String {
- var url = baseUrl.trim()
- while (url.endsWith('/')) {
- url = url.dropLast(1)
- }
-
- return url
- }
-
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeString(hostname)
- parcel.writeString(roomId)
- parcel.writeString(type.toString())
- parcel.writeString(name)
- parcel.writeParcelable(sender, flags)
- }
-
- override fun describeContents(): Int {
- return 0
- }
-
- companion object CREATOR : Parcelable.Creator {
- val EMPTY = PushInfo(hostname = "", roomId = "", type = roomTypeOf(RoomType.CHANNEL), name = "",
- sender = null)
-
- override fun createFromParcel(parcel: Parcel): PushInfo {
- return PushInfo(parcel)
- }
-
- override fun newArray(size: Int): Array {
- return arrayOfNulls(size)
- }
- }
-}
-
-@JsonSerializable
-data class PushSender @KotshiConstructor constructor(
- @Json(name = "_id") val id: String,
- val username: String?,
- val name: String?
-) : Parcelable {
- constructor(parcel: Parcel) : this(
- parcel.readString().orEmpty(),
- parcel.readString(),
- parcel.readString())
-
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeString(id)
- parcel.writeString(username)
- parcel.writeString(name)
- }
-
- override fun describeContents(): Int {
- return 0
- }
-
- companion object CREATOR : Parcelable.Creator {
- override fun createFromParcel(parcel: Parcel): PushSender {
- return PushSender(parcel)
- }
-
- override fun newArray(size: Int): Array {
- return arrayOfNulls(size)
- }
- }
-}
-
const val EXTRA_NOT_ID = "chat.rocket.android.EXTRA_NOT_ID"
-const val EXTRA_HOSTNAME = "chat.rocket.android.EXTRA_HOSTNAME"
-const val EXTRA_PUSH_MESSAGE = "chat.rocket.android.EXTRA_PUSH_MESSAGE"
-const val EXTRA_ROOM_ID = "chat.rocket.android.EXTRA_ROOM_ID"
-const val ACTION_REPLY = "chat.rocket.android.ACTION_REPLY"
-const val REMOTE_INPUT_REPLY = "REMOTE_INPUT_REPLY"
+const val EXTRA_HOSTNAME = "chat.rocket.android.EXTRA_HOSTNAME"
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/push/PushMessage.kt b/app/src/main/java/chat/rocket/android/push/PushMessage.kt
new file mode 100644
index 0000000000..7ca88f9cff
--- /dev/null
+++ b/app/src/main/java/chat/rocket/android/push/PushMessage.kt
@@ -0,0 +1,12 @@
+package chat.rocket.android.push
+
+data class PushMessage(
+ val title: String,
+ val message: String,
+ val info: PushInfo,
+ val image: String? = null,
+ val count: String? = null,
+ val notificationId: String,
+ val summaryText: String? = null,
+ val style: String? = null
+)
diff --git a/app/src/main/java/chat/rocket/android/push/PushSender.kt b/app/src/main/java/chat/rocket/android/push/PushSender.kt
new file mode 100644
index 0000000000..556aac9646
--- /dev/null
+++ b/app/src/main/java/chat/rocket/android/push/PushSender.kt
@@ -0,0 +1,11 @@
+package chat.rocket.android.push
+
+import com.squareup.moshi.Json
+import se.ansman.kotshi.JsonSerializable
+
+@JsonSerializable
+data class PushSender constructor(
+ @Json(name = "_id") val id: String,
+ val username: String?,
+ val name: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/chat/rocket/android/server/di/ChangeServerModule.kt b/app/src/main/java/chat/rocket/android/server/di/ChangeServerModule.kt
index bc0b67cb4d..7764b058e1 100644
--- a/app/src/main/java/chat/rocket/android/server/di/ChangeServerModule.kt
+++ b/app/src/main/java/chat/rocket/android/server/di/ChangeServerModule.kt
@@ -15,7 +15,7 @@ class ChangeServerModule {
@Provides
@PerActivity
- fun provideJob() = Job()
+ fun provideJob(): Job = Job()
@Provides
@PerActivity
diff --git a/app/src/main/java/chat/rocket/android/server/domain/ChatRoomsInteractor.kt b/app/src/main/java/chat/rocket/android/server/domain/ChatRoomsInteractor.kt
index e57bbafb87..9b4dde8b0b 100644
--- a/app/src/main/java/chat/rocket/android/server/domain/ChatRoomsInteractor.kt
+++ b/app/src/main/java/chat/rocket/android/server/domain/ChatRoomsInteractor.kt
@@ -30,7 +30,7 @@ class ChatRoomsInteractor @Inject constructor(private val repository: ChatRoomsR
return@withContext allChatRooms
}
return@withContext allChatRooms.filter {
- it.name.contains(name, true)
+ it.name?.contains(name, true) == true
}
}
diff --git a/app/src/main/java/chat/rocket/android/server/infrastructure/ConnectionManager.kt b/app/src/main/java/chat/rocket/android/server/infrastructure/ConnectionManager.kt
index b889354309..d7e5f96ba0 100644
--- a/app/src/main/java/chat/rocket/android/server/infrastructure/ConnectionManager.kt
+++ b/app/src/main/java/chat/rocket/android/server/infrastructure/ConnectionManager.kt
@@ -126,23 +126,14 @@ class ConnectionManager(
dbManager.processUsersBatch(users)
}
- launch {
- for (room in client.roomsChannel) {
- Timber.d("Got room streamed")
- roomsActor.send(room)
- }
+ launch { for (room in client.roomsChannel) roomsActor.send(room) }
- for (subscription in client.subscriptionsChannel) {
- Timber.d("Got subscription streamed")
- roomsActor.send(subscription)
- }
+ launch { for (subscription in client.subscriptionsChannel) roomsActor.send(subscription) }
- for (user in client.activeUsersChannel) {
- userActor.send(user)
- }
- }
+ launch { for (user in client.activeUsersChannel) userActor.send(user) }
}
+
fun addStateChannel(channel: Channel) = stateChannelList.add(channel)
fun removeStateChannel(channel: Channel) = stateChannelList.remove(channel)
diff --git a/app/src/main/java/chat/rocket/android/server/infrastructure/RocketChatClientFactory.kt b/app/src/main/java/chat/rocket/android/server/infrastructure/RocketChatClientFactory.kt
index 0c5ab18cbb..a35c2c9039 100644
--- a/app/src/main/java/chat/rocket/android/server/infrastructure/RocketChatClientFactory.kt
+++ b/app/src/main/java/chat/rocket/android/server/infrastructure/RocketChatClientFactory.kt
@@ -5,6 +5,7 @@ import chat.rocket.android.BuildConfig
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.RocketChatClient
+import chat.rocket.core.createRocketChatClient
import okhttp3.OkHttpClient
import timber.log.Timber
import javax.inject.Inject
@@ -24,7 +25,7 @@ class RocketChatClientFactory @Inject constructor(
return it
}
- val client = RocketChatClient.create {
+ val client = createRocketChatClient {
httpClient = okHttpClient
restUrl = url
userAgent = "RC Mobile; Android ${Build.VERSION.RELEASE}; v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
diff --git a/app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt b/app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt
index 1ab78f1451..171a1b8059 100644
--- a/app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt
+++ b/app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt
@@ -6,10 +6,9 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.helper.OauthHelper
-import chat.rocket.android.infrastructure.LocalRepository
-import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.PublicSettings
+import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.casLoginUrl
import chat.rocket.android.server.domain.gitlabUrl
import chat.rocket.android.server.domain.isCasAuthenticationEnabled
@@ -22,10 +21,6 @@ import chat.rocket.android.server.domain.isLoginFormEnabled
import chat.rocket.android.server.domain.isRegistrationEnabledForNewUsers
import chat.rocket.android.server.domain.isWordpressAuthenticationEnabled
import chat.rocket.android.server.domain.wordpressUrl
-import chat.rocket.android.server.domain.GetCurrentServerInteractor
-import chat.rocket.android.server.domain.RemoveAccountInteractor
-import chat.rocket.android.server.domain.TokenRepository
-import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.infrastructure.ConnectionManager
import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.server.infrastructure.RocketChatClientFactory
@@ -40,17 +35,10 @@ import chat.rocket.common.RocketChatException
import chat.rocket.common.RocketChatInvalidProtocolException
import chat.rocket.common.model.ServerInfo
import chat.rocket.core.RocketChatClient
-import chat.rocket.core.internal.rest.logout
import chat.rocket.core.internal.rest.serverInfo
import chat.rocket.core.internal.rest.settingsOauth
-import chat.rocket.core.internal.rest.unregisterPushToken
-import chat.rocket.core.model.Myself
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.withContext
import timber.log.Timber
-import javax.inject.Named
private const val SERVICE_NAME_FACEBOOK = "facebook"
private const val SERVICE_NAME_GITHUB = "github"
@@ -62,17 +50,10 @@ private const val SERVICE_NAME_WORDPRESS = "wordpress"
abstract class CheckServerPresenter constructor(
private val strategy: CancelStrategy,
private val factory: RocketChatClientFactory,
- @Named("currentServer") private val currentSavedServer: String?,
private val settingsInteractor: GetSettingsInteractor? = null,
- private val serverInteractor: GetCurrentServerInteractor? = null,
- private val localRepository: LocalRepository? = null,
- private val removeAccountInteractor: RemoveAccountInteractor? = null,
- private val tokenRepository: TokenRepository? = null,
private val managerFactory: ConnectionManagerFactory? = null,
private val dbManagerFactory: DatabaseManagerFactory? = null,
private val versionCheckView: VersionCheckView? = null,
- private val tokenView: TokenView? = null,
- private val navigator: MainNavigator? = null,
private val refreshSettingsInteractor: RefreshSettingsInteractor? = null
) {
private lateinit var currentServer: String
@@ -202,46 +183,6 @@ abstract class CheckServerPresenter constructor(
}
}
- /**
- * Logout the user from the current server.
- */
- internal fun logout() {
- launchUI(strategy) {
- try {
- clearTokens()
- retryIO("logout") { client?.logout() }
- } catch (exception: RocketChatException) {
- Timber.e(exception, "Error calling logout")
- }
-
- try {
- connectionManager?.disconnect()
- currentSavedServer?.let {
- removeAccountInteractor?.remove(it)
- tokenRepository?.remove(it)
- }
- withContext(Dispatchers.IO) { dbManager?.logout() }
- navigator?.switchOrAddNewServer()
- } catch (ex: Exception) {
- Timber.e(ex, "Error cleaning up the session...")
- }
- }
- }
-
- private suspend fun clearTokens() {
- serverInteractor?.clear()
- val pushToken = localRepository?.get(LocalRepository.KEY_PUSH_TOKEN)
- if (pushToken != null) {
- try {
- retryIO("unregisterPushToken") { client?.unregisterPushToken(pushToken) }
- tokenView?.invalidateToken(pushToken)
- } catch (ex: Exception) {
- Timber.e(ex, "Error unregistering push token")
- }
- }
- localRepository?.clearAllFromServer(currentServer)
- }
-
private fun checkEnabledOauthAccounts(services: List