mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-12-18 14:42:16 +03:00
add referenceId for "normal" sending of chat message
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
f41efd9303
commit
76448e8572
14 changed files with 883 additions and 97 deletions
|
@ -0,0 +1,731 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 13,
|
||||||
|
"identityHash": "6986b68476bae871773348987eada812",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "User",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userId` TEXT, `username` TEXT, `baseUrl` TEXT, `token` TEXT, `displayName` TEXT, `pushConfigurationState` TEXT, `capabilities` TEXT, `serverVersion` TEXT DEFAULT '', `clientCertificate` TEXT, `externalSignalingServer` TEXT, `current` INTEGER NOT NULL, `scheduledForDeletion` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userId",
|
||||||
|
"columnName": "userId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "username",
|
||||||
|
"columnName": "username",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "baseUrl",
|
||||||
|
"columnName": "baseUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "displayName",
|
||||||
|
"columnName": "displayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pushConfigurationState",
|
||||||
|
"columnName": "pushConfigurationState",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "capabilities",
|
||||||
|
"columnName": "capabilities",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serverVersion",
|
||||||
|
"columnName": "serverVersion",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "clientCertificate",
|
||||||
|
"columnName": "clientCertificate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "externalSignalingServer",
|
||||||
|
"columnName": "externalSignalingServer",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "current",
|
||||||
|
"columnName": "current",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "scheduledForDeletion",
|
||||||
|
"columnName": "scheduledForDeletion",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ArbitraryStorage",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountIdentifier` INTEGER NOT NULL, `key` TEXT NOT NULL, `object` TEXT, `value` TEXT, PRIMARY KEY(`accountIdentifier`, `key`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "accountIdentifier",
|
||||||
|
"columnName": "accountIdentifier",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "key",
|
||||||
|
"columnName": "key",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "storageObject",
|
||||||
|
"columnName": "object",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "value",
|
||||||
|
"columnName": "value",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"accountIdentifier",
|
||||||
|
"key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Conversations",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `displayName` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `avatarVersion` TEXT NOT NULL, `callFlag` INTEGER NOT NULL, `callRecording` INTEGER NOT NULL, `callStartTime` INTEGER NOT NULL, `canDeleteConversation` INTEGER NOT NULL, `canLeaveConversation` INTEGER NOT NULL, `canStartCall` INTEGER NOT NULL, `description` TEXT NOT NULL, `hasCall` INTEGER NOT NULL, `hasPassword` INTEGER NOT NULL, `isCustomAvatar` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL, `lastActivity` INTEGER NOT NULL, `lastCommonReadMessage` INTEGER NOT NULL, `lastMessage` TEXT, `lastPing` INTEGER NOT NULL, `lastReadMessage` INTEGER NOT NULL, `lobbyState` TEXT NOT NULL, `lobbyTimer` INTEGER NOT NULL, `messageExpiration` INTEGER NOT NULL, `name` TEXT NOT NULL, `notificationCalls` INTEGER NOT NULL, `notificationLevel` TEXT NOT NULL, `objectType` TEXT NOT NULL, `participantType` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `readOnly` TEXT NOT NULL, `recordingConsent` INTEGER NOT NULL, `remoteServer` TEXT, `remoteToken` TEXT, `sessionId` TEXT NOT NULL, `status` TEXT, `statusClearAt` INTEGER, `statusIcon` TEXT, `statusMessage` TEXT, `type` TEXT NOT NULL, `unreadMention` INTEGER NOT NULL, `unreadMentionDirect` INTEGER NOT NULL, `unreadMessages` INTEGER NOT NULL, `hasArchived` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`accountId`) REFERENCES `User`(`id`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "internalId",
|
||||||
|
"columnName": "internalId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "displayName",
|
||||||
|
"columnName": "displayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorId",
|
||||||
|
"columnName": "actorId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorType",
|
||||||
|
"columnName": "actorType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "avatarVersion",
|
||||||
|
"columnName": "avatarVersion",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callFlag",
|
||||||
|
"columnName": "callFlag",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callRecording",
|
||||||
|
"columnName": "callRecording",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "callStartTime",
|
||||||
|
"columnName": "callStartTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canDeleteConversation",
|
||||||
|
"columnName": "canDeleteConversation",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canLeaveConversation",
|
||||||
|
"columnName": "canLeaveConversation",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "canStartCall",
|
||||||
|
"columnName": "canStartCall",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasCall",
|
||||||
|
"columnName": "hasCall",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasPassword",
|
||||||
|
"columnName": "hasPassword",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasCustomAvatar",
|
||||||
|
"columnName": "isCustomAvatar",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "favorite",
|
||||||
|
"columnName": "isFavorite",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastActivity",
|
||||||
|
"columnName": "lastActivity",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastCommonReadMessage",
|
||||||
|
"columnName": "lastCommonReadMessage",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastMessage",
|
||||||
|
"columnName": "lastMessage",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastPing",
|
||||||
|
"columnName": "lastPing",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastReadMessage",
|
||||||
|
"columnName": "lastReadMessage",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lobbyState",
|
||||||
|
"columnName": "lobbyState",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lobbyTimer",
|
||||||
|
"columnName": "lobbyTimer",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageExpiration",
|
||||||
|
"columnName": "messageExpiration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "notificationCalls",
|
||||||
|
"columnName": "notificationCalls",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "notificationLevel",
|
||||||
|
"columnName": "notificationLevel",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "objectType",
|
||||||
|
"columnName": "objectType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "participantType",
|
||||||
|
"columnName": "participantType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "permissions",
|
||||||
|
"columnName": "permissions",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "conversationReadOnlyState",
|
||||||
|
"columnName": "readOnly",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "recordingConsentRequired",
|
||||||
|
"columnName": "recordingConsent",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteServer",
|
||||||
|
"columnName": "remoteServer",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "remoteToken",
|
||||||
|
"columnName": "remoteToken",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sessionId",
|
||||||
|
"columnName": "sessionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusClearAt",
|
||||||
|
"columnName": "statusClearAt",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusIcon",
|
||||||
|
"columnName": "statusIcon",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "statusMessage",
|
||||||
|
"columnName": "statusMessage",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMention",
|
||||||
|
"columnName": "unreadMention",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMentionDirect",
|
||||||
|
"columnName": "unreadMentionDirect",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "unreadMessages",
|
||||||
|
"columnName": "unreadMessages",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasArchived",
|
||||||
|
"columnName": "hasArchived",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Conversations_accountId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"accountId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Conversations_accountId` ON `${TABLE_NAME}` (`accountId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "User",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"accountId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ChatMessages",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `accountId` INTEGER NOT NULL, `token` TEXT NOT NULL, `id` INTEGER NOT NULL, `internalConversationId` TEXT NOT NULL, `actorDisplayName` TEXT NOT NULL, `message` TEXT NOT NULL, `actorId` TEXT NOT NULL, `actorType` TEXT NOT NULL, `deleted` INTEGER NOT NULL, `expirationTimestamp` INTEGER NOT NULL, `isReplyable` INTEGER NOT NULL, `lastEditActorDisplayName` TEXT, `lastEditActorId` TEXT, `lastEditActorType` TEXT, `lastEditTimestamp` INTEGER, `markdown` INTEGER, `messageParameters` TEXT, `messageType` TEXT NOT NULL, `parent` INTEGER, `reactions` TEXT, `reactionsSelf` TEXT, `referenceId` TEXT, `systemMessage` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`internalId`), FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "internalId",
|
||||||
|
"columnName": "internalId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "internalConversationId",
|
||||||
|
"columnName": "internalConversationId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorDisplayName",
|
||||||
|
"columnName": "actorDisplayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "message",
|
||||||
|
"columnName": "message",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorId",
|
||||||
|
"columnName": "actorId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "actorType",
|
||||||
|
"columnName": "actorType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "deleted",
|
||||||
|
"columnName": "deleted",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "expirationTimestamp",
|
||||||
|
"columnName": "expirationTimestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "replyable",
|
||||||
|
"columnName": "isReplyable",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorDisplayName",
|
||||||
|
"columnName": "lastEditActorDisplayName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorId",
|
||||||
|
"columnName": "lastEditActorId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditActorType",
|
||||||
|
"columnName": "lastEditActorType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastEditTimestamp",
|
||||||
|
"columnName": "lastEditTimestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "renderMarkdown",
|
||||||
|
"columnName": "markdown",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageParameters",
|
||||||
|
"columnName": "messageParameters",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "messageType",
|
||||||
|
"columnName": "messageType",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parentMessageId",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "reactions",
|
||||||
|
"columnName": "reactions",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "reactionsSelf",
|
||||||
|
"columnName": "reactionsSelf",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "referenceId",
|
||||||
|
"columnName": "referenceId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "systemMessageType",
|
||||||
|
"columnName": "systemMessage",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "timestamp",
|
||||||
|
"columnName": "timestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_ChatMessages_internalId",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"internalId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_ChatMessages_internalId` ON `${TABLE_NAME}` (`internalId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_ChatMessages_internalConversationId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_ChatMessages_internalConversationId` ON `${TABLE_NAME}` (`internalConversationId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Conversations",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "ChatBlocks",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `internalConversationId` TEXT NOT NULL, `accountId` INTEGER, `token` TEXT, `oldestMessageId` INTEGER NOT NULL, `newestMessageId` INTEGER NOT NULL, `hasHistory` INTEGER NOT NULL, FOREIGN KEY(`internalConversationId`) REFERENCES `Conversations`(`internalId`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "internalConversationId",
|
||||||
|
"columnName": "internalConversationId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "accountId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "token",
|
||||||
|
"columnName": "token",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "oldestMessageId",
|
||||||
|
"columnName": "oldestMessageId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "newestMessageId",
|
||||||
|
"columnName": "newestMessageId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasHistory",
|
||||||
|
"columnName": "hasHistory",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_ChatBlocks_internalConversationId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_ChatBlocks_internalConversationId` ON `${TABLE_NAME}` (`internalConversationId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Conversations",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"internalConversationId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"internalId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6986b68476bae871773348987eada812')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -344,12 +344,14 @@ public interface NcApi {
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> sendChatMessage(@Header("Authorization") String authorization,
|
Observable<ChatOverallSingleMessage> sendChatMessage(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("message") CharSequence message,
|
@Field("message") CharSequence message,
|
||||||
@Field("actorDisplayName") String actorDisplayName,
|
@Field("actorDisplayName") String actorDisplayName,
|
||||||
@Field("replyTo") Integer replyTo,
|
@Field("replyTo") Integer replyTo,
|
||||||
@Field("silent") Boolean sendWithoutNotification);
|
@Field("silent") Boolean sendWithoutNotification,
|
||||||
|
@Field("referenceId") String referenceId
|
||||||
|
);
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@PUT
|
@PUT
|
||||||
|
|
|
@ -115,9 +115,12 @@ data class ChatMessage(
|
||||||
|
|
||||||
var isTempMessage: Boolean = false,
|
var isTempMessage: Boolean = false,
|
||||||
|
|
||||||
var tempMessageId: Int = -1
|
var tempMessageId: Int = -1,
|
||||||
|
|
||||||
) : MessageContentType, MessageContentType.Image {
|
var referenceId: String? = null
|
||||||
|
|
||||||
|
) : MessageContentType,
|
||||||
|
MessageContentType.Image {
|
||||||
|
|
||||||
var extractedUrlToPreview: String? = null
|
var extractedUrlToPreview: String? = null
|
||||||
|
|
||||||
|
@ -238,8 +241,8 @@ data class ChatMessage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalculateMessageType(): MessageType {
|
fun getCalculateMessageType(): MessageType =
|
||||||
return if (!TextUtils.isEmpty(systemMessage)) {
|
if (!TextUtils.isEmpty(systemMessage)) {
|
||||||
MessageType.SYSTEM_MESSAGE
|
MessageType.SYSTEM_MESSAGE
|
||||||
} else if (isVoiceMessage) {
|
} else if (isVoiceMessage) {
|
||||||
MessageType.VOICE_MESSAGE
|
MessageType.VOICE_MESSAGE
|
||||||
|
@ -254,19 +257,15 @@ data class ChatMessage(
|
||||||
} else {
|
} else {
|
||||||
MessageType.REGULAR_TEXT_MESSAGE
|
MessageType.REGULAR_TEXT_MESSAGE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId(): String {
|
override fun getId(): String = jsonMessageId.toString()
|
||||||
return jsonMessageId.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getText(): String {
|
override fun getText(): String =
|
||||||
return if (message != null) {
|
if (message != null) {
|
||||||
getParsedMessage(message, messageParameters)!!
|
getParsedMessage(message, messageParameters)!!
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun getNullsafeActorDisplayName() =
|
fun getNullsafeActorDisplayName() =
|
||||||
if (!TextUtils.isEmpty(actorDisplayName)) {
|
if (!TextUtils.isEmpty(actorDisplayName)) {
|
||||||
|
@ -275,22 +274,19 @@ data class ChatMessage(
|
||||||
sharedApplication!!.getString(R.string.nc_guest)
|
sharedApplication!!.getString(R.string.nc_guest)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUser(): IUser {
|
override fun getUser(): IUser =
|
||||||
return object : IUser {
|
object : IUser {
|
||||||
override fun getId(): String {
|
override fun getId(): String = "$actorType/$actorId"
|
||||||
return "$actorType/$actorId"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getName(): String {
|
override fun getName(): String =
|
||||||
return if (!TextUtils.isEmpty(actorDisplayName)) {
|
if (!TextUtils.isEmpty(actorDisplayName)) {
|
||||||
actorDisplayName!!
|
actorDisplayName!!
|
||||||
} else {
|
} else {
|
||||||
sharedApplication!!.getString(R.string.nc_guest)
|
sharedApplication!!.getString(R.string.nc_guest)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun getAvatar(): String? {
|
override fun getAvatar(): String? =
|
||||||
return when {
|
when {
|
||||||
activeUser == null -> {
|
activeUser == null -> {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -312,21 +308,14 @@ data class ChatMessage(
|
||||||
ApiUtils.getUrlForGuestAvatar(activeUser!!.baseUrl!!, apiId, true)
|
ApiUtils.getUrlForGuestAvatar(activeUser!!.baseUrl!!, apiId, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCreatedAt(): Date {
|
override fun getCreatedAt(): Date = Date(timestamp * MILLIES)
|
||||||
return Date(timestamp * MILLIES)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSystemMessage(): String {
|
override fun getSystemMessage(): String = EnumSystemMessageTypeConverter().convertToString(systemMessageType)
|
||||||
return EnumSystemMessageTypeConverter().convertToString(systemMessageType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isHashMapEntryEqualTo(map: HashMap<String?, String?>, key: String, searchTerm: String): Boolean {
|
private fun isHashMapEntryEqualTo(map: HashMap<String?, String?>, key: String, searchTerm: String): Boolean =
|
||||||
return map != null && MessageDigest.isEqual(map[key]!!.toByteArray(), searchTerm.toByteArray())
|
map != null && MessageDigest.isEqual(map[key]!!.toByteArray(), searchTerm.toByteArray())
|
||||||
}
|
|
||||||
|
|
||||||
// needed a equals and hashcode function to fix detekt errors
|
// needed a equals and hashcode function to fix detekt errors
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
@ -335,9 +324,7 @@ data class ChatMessage(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int = 0
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val isVoiceMessage: Boolean
|
val isVoiceMessage: Boolean
|
||||||
get() = "voice-message" == messageType
|
get() = "voice-message" == messageType
|
||||||
|
|
|
@ -37,7 +37,7 @@ interface ChatNetworkDataSource {
|
||||||
url: String,
|
url: String,
|
||||||
message: String,
|
message: String,
|
||||||
displayName: String
|
displayName: String
|
||||||
): Observable<GenericOverall> // last two fields are false
|
): Observable<ChatOverallSingleMessage>
|
||||||
|
|
||||||
fun checkForNoteToSelf(credentials: String, url: String, includeStatus: Boolean): Observable<RoomsOverall>
|
fun checkForNoteToSelf(credentials: String, url: String, includeStatus: Boolean): Observable<RoomsOverall>
|
||||||
fun shareLocationToNotes(
|
fun shareLocationToNotes(
|
||||||
|
@ -55,8 +55,9 @@ interface ChatNetworkDataSource {
|
||||||
message: CharSequence,
|
message: CharSequence,
|
||||||
displayName: String,
|
displayName: String,
|
||||||
replyTo: Int,
|
replyTo: Int,
|
||||||
sendWithoutNotification: Boolean
|
sendWithoutNotification: Boolean,
|
||||||
): Observable<GenericOverall>
|
referenceId: String
|
||||||
|
): Observable<ChatOverallSingleMessage>
|
||||||
|
|
||||||
fun pullChatMessages(credentials: String, url: String, fieldMap: HashMap<String, Int>): Observable<Response<*>>
|
fun pullChatMessages(credentials: String, url: String, fieldMap: HashMap<String, Int>): Observable<Response<*>>
|
||||||
fun deleteChatMessage(credentials: String, url: String): Observable<ChatOverallSingleMessage>
|
fun deleteChatMessage(credentials: String, url: String): Observable<ChatOverallSingleMessage>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.models.json.reminder.Reminder
|
import com.nextcloud.talk.models.json.reminder.Reminder
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.message.SendMessageUtils
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
|
||||||
|
@ -103,26 +104,24 @@ class RetrofitChatNetwork(private val ncApi: NcApi) : ChatNetworkDataSource {
|
||||||
url: String,
|
url: String,
|
||||||
message: String,
|
message: String,
|
||||||
displayName: String
|
displayName: String
|
||||||
): Observable<GenericOverall> {
|
): Observable<ChatOverallSingleMessage> =
|
||||||
return ncApi.sendChatMessage(
|
ncApi.sendChatMessage(
|
||||||
credentials,
|
credentials,
|
||||||
url,
|
url,
|
||||||
message,
|
message,
|
||||||
displayName,
|
displayName,
|
||||||
null,
|
null,
|
||||||
false
|
false,
|
||||||
|
SendMessageUtils().generateReferenceId() // TODO add temp message before with ref id..
|
||||||
).map {
|
).map {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun checkForNoteToSelf(
|
override fun checkForNoteToSelf(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
url: String,
|
url: String,
|
||||||
includeStatus: Boolean
|
includeStatus: Boolean
|
||||||
): Observable<RoomsOverall> {
|
): Observable<RoomsOverall> = ncApi.getRooms(credentials, url, includeStatus).map { it }
|
||||||
return ncApi.getRooms(credentials, url, includeStatus).map { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shareLocationToNotes(
|
override fun shareLocationToNotes(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
|
@ -130,13 +129,12 @@ class RetrofitChatNetwork(private val ncApi: NcApi) : ChatNetworkDataSource {
|
||||||
objectType: String,
|
objectType: String,
|
||||||
objectId: String,
|
objectId: String,
|
||||||
metadata: String
|
metadata: String
|
||||||
): Observable<GenericOverall> {
|
): Observable<GenericOverall> = ncApi.sendLocation(credentials, url, objectType, objectId, metadata).map { it }
|
||||||
return ncApi.sendLocation(credentials, url, objectType, objectId, metadata).map { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun leaveRoom(credentials: String, url: String): Observable<GenericOverall> {
|
override fun leaveRoom(credentials: String, url: String): Observable<GenericOverall> =
|
||||||
return ncApi.leaveRoom(credentials, url).map { it }
|
ncApi.leaveRoom(credentials, url).map {
|
||||||
}
|
it
|
||||||
|
}
|
||||||
|
|
||||||
override fun sendChatMessage(
|
override fun sendChatMessage(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
|
@ -144,36 +142,42 @@ class RetrofitChatNetwork(private val ncApi: NcApi) : ChatNetworkDataSource {
|
||||||
message: CharSequence,
|
message: CharSequence,
|
||||||
displayName: String,
|
displayName: String,
|
||||||
replyTo: Int,
|
replyTo: Int,
|
||||||
sendWithoutNotification: Boolean
|
sendWithoutNotification: Boolean,
|
||||||
): Observable<GenericOverall> {
|
referenceId: String
|
||||||
return ncApi.sendChatMessage(credentials, url, message, displayName, replyTo, sendWithoutNotification).map {
|
): Observable<ChatOverallSingleMessage> =
|
||||||
|
ncApi.sendChatMessage(
|
||||||
|
credentials,
|
||||||
|
url,
|
||||||
|
message,
|
||||||
|
displayName,
|
||||||
|
replyTo,
|
||||||
|
sendWithoutNotification,
|
||||||
|
referenceId
|
||||||
|
).map {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun pullChatMessages(
|
override fun pullChatMessages(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
url: String,
|
url: String,
|
||||||
fieldMap: HashMap<String, Int>
|
fieldMap: HashMap<String, Int>
|
||||||
): Observable<Response<*>> {
|
): Observable<Response<*>> = ncApi.pullChatMessages(credentials, url, fieldMap).map { it }
|
||||||
return ncApi.pullChatMessages(credentials, url, fieldMap).map { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deleteChatMessage(credentials: String, url: String): Observable<ChatOverallSingleMessage> {
|
override fun deleteChatMessage(credentials: String, url: String): Observable<ChatOverallSingleMessage> =
|
||||||
return ncApi.deleteChatMessage(credentials, url).map { it }
|
ncApi.deleteChatMessage(credentials, url).map {
|
||||||
}
|
it
|
||||||
|
}
|
||||||
|
|
||||||
override fun createRoom(credentials: String, url: String, map: Map<String, String>): Observable<RoomOverall> {
|
override fun createRoom(credentials: String, url: String, map: Map<String, String>): Observable<RoomOverall> =
|
||||||
return ncApi.createRoom(credentials, url, map).map { it }
|
ncApi.createRoom(credentials, url, map).map {
|
||||||
}
|
it
|
||||||
|
}
|
||||||
|
|
||||||
override fun setChatReadMarker(
|
override fun setChatReadMarker(
|
||||||
credentials: String,
|
credentials: String,
|
||||||
url: String,
|
url: String,
|
||||||
previousMessageId: Int
|
previousMessageId: Int
|
||||||
): Observable<GenericOverall> {
|
): Observable<GenericOverall> = ncApi.setChatReadMarker(credentials, url, previousMessageId).map { it }
|
||||||
return ncApi.setChatReadMarker(credentials, url, previousMessageId).map { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun editChatMessage(credentials: String, url: String, text: String): Observable<ChatOverallSingleMessage> {
|
override fun editChatMessage(credentials: String, url: String, text: String): Observable<ChatOverallSingleMessage> {
|
||||||
return ncApi.editChatMessage(credentials, url, text).map { it }
|
return ncApi.editChatMessage(credentials, url, text).map { it }
|
||||||
|
|
|
@ -60,7 +60,8 @@ class ChatViewModel @Inject constructor(
|
||||||
private val mediaRecorderManager: MediaRecorderManager,
|
private val mediaRecorderManager: MediaRecorderManager,
|
||||||
private val audioFocusRequestManager: AudioFocusRequestManager,
|
private val audioFocusRequestManager: AudioFocusRequestManager,
|
||||||
private val userProvider: CurrentUserProviderNew
|
private val userProvider: CurrentUserProviderNew
|
||||||
) : ViewModel(), DefaultLifecycleObserver {
|
) : ViewModel(),
|
||||||
|
DefaultLifecycleObserver {
|
||||||
|
|
||||||
enum class LifeCycleFlag {
|
enum class LifeCycleFlag {
|
||||||
PAUSED,
|
PAUSED,
|
||||||
|
@ -466,12 +467,12 @@ class ChatViewModel @Inject constructor(
|
||||||
chatNetworkDataSource.shareToNotes(credentials, url, message, displayName)
|
chatNetworkDataSource.shareToNotes(credentials, url, message, displayName)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
?.subscribe(object : Observer<GenericOverall> {
|
?.subscribe(object : Observer<ChatOverallSingleMessage> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
disposableSet.add(d)
|
disposableSet.add(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(genericOverall: GenericOverall) {
|
override fun onNext(genericOverall: ChatOverallSingleMessage) {
|
||||||
// unused atm
|
// unused atm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,9 +598,7 @@ class ChatViewModel @Inject constructor(
|
||||||
cachedFile.delete()
|
cachedFile.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentVoiceRecordFile(): String {
|
fun getCurrentVoiceRecordFile(): String = mediaRecorderManager.currentVoiceRecordFile
|
||||||
return mediaRecorderManager.currentVoiceRecordFile
|
|
||||||
}
|
|
||||||
|
|
||||||
fun uploadFile(fileUri: String, room: String, displayName: String, metaData: String) {
|
fun uploadFile(fileUri: String, room: String, displayName: String, metaData: String) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import com.nextcloud.talk.chat.data.io.MediaPlayerManager
|
||||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||||
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
||||||
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
|
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.utils.message.SendMessageUtils
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import com.stfalcon.chatkit.commons.models.IMessage
|
import com.stfalcon.chatkit.commons.models.IMessage
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
|
@ -39,7 +39,8 @@ class MessageInputViewModel @Inject constructor(
|
||||||
private val mediaPlayerManager: MediaPlayerManager,
|
private val mediaPlayerManager: MediaPlayerManager,
|
||||||
private val audioFocusRequestManager: AudioFocusRequestManager,
|
private val audioFocusRequestManager: AudioFocusRequestManager,
|
||||||
private val appPreferences: AppPreferences
|
private val appPreferences: AppPreferences
|
||||||
) : ViewModel(), DefaultLifecycleObserver {
|
) : ViewModel(),
|
||||||
|
DefaultLifecycleObserver {
|
||||||
enum class LifeCycleFlag {
|
enum class LifeCycleFlag {
|
||||||
PAUSED,
|
PAUSED,
|
||||||
RESUMED,
|
RESUMED,
|
||||||
|
@ -144,6 +145,11 @@ class MessageInputViewModel @Inject constructor(
|
||||||
replyTo: Int,
|
replyTo: Int,
|
||||||
sendWithoutNotification: Boolean
|
sendWithoutNotification: Boolean
|
||||||
) {
|
) {
|
||||||
|
// TODO: add temporary message with ref id
|
||||||
|
|
||||||
|
val referenceId = SendMessageUtils().generateReferenceId()
|
||||||
|
Log.d(TAG, "Random SHA-256 Hash: $referenceId")
|
||||||
|
|
||||||
if (isQueueing) {
|
if (isQueueing) {
|
||||||
val tempID = System.currentTimeMillis().toInt()
|
val tempID = System.currentTimeMillis().toInt()
|
||||||
val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification)
|
val qMsg = QueuedMessage(tempID, message, displayName, replyTo, sendWithoutNotification)
|
||||||
|
@ -161,10 +167,11 @@ class MessageInputViewModel @Inject constructor(
|
||||||
message,
|
message,
|
||||||
displayName,
|
displayName,
|
||||||
replyTo,
|
replyTo,
|
||||||
sendWithoutNotification
|
sendWithoutNotification,
|
||||||
|
referenceId
|
||||||
).subscribeOn(Schedulers.io())
|
).subscribeOn(Schedulers.io())
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
?.subscribe(object : Observer<GenericOverall> {
|
?.subscribe(object : Observer<ChatOverallSingleMessage> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
disposableSet.add(d)
|
disposableSet.add(d)
|
||||||
}
|
}
|
||||||
|
@ -177,7 +184,9 @@ class MessageInputViewModel @Inject constructor(
|
||||||
// unused atm
|
// unused atm
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(t: GenericOverall) {
|
override fun onNext(t: ChatOverallSingleMessage) {
|
||||||
|
Log.d(TAG, "received ref id: " + (t.ocs?.data?.referenceId ?: "none"))
|
||||||
|
// TODO check ref id and replace temp message
|
||||||
_sendChatMessageViewState.value = SendChatMessageSuccessState(message)
|
_sendChatMessageViewState.value = SendChatMessageSuccessState(message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,7 +37,8 @@ fun ChatMessageJson.asEntity(accountId: Long) =
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp,
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
deleted = deleted
|
deleted = deleted,
|
||||||
|
referenceId = referenceId
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ChatMessageEntity.asModel() =
|
fun ChatMessageEntity.asModel() =
|
||||||
|
@ -62,7 +63,8 @@ fun ChatMessageEntity.asModel() =
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp,
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
isDeleted = deleted
|
isDeleted = deleted,
|
||||||
|
referenceId = referenceId
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ChatMessageJson.asModel() =
|
fun ChatMessageJson.asModel() =
|
||||||
|
@ -87,5 +89,6 @@ fun ChatMessageJson.asModel() =
|
||||||
lastEditActorId = lastEditActorId,
|
lastEditActorId = lastEditActorId,
|
||||||
lastEditActorType = lastEditActorType,
|
lastEditActorType = lastEditActorType,
|
||||||
lastEditTimestamp = lastEditTimestamp,
|
lastEditTimestamp = lastEditTimestamp,
|
||||||
isDeleted = deleted
|
isDeleted = deleted,
|
||||||
|
referenceId = referenceId
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,8 +62,8 @@ data class ChatMessageEntity(
|
||||||
@ColumnInfo(name = "parent") var parentMessageId: Long? = null,
|
@ColumnInfo(name = "parent") var parentMessageId: Long? = null,
|
||||||
@ColumnInfo(name = "reactions") var reactions: LinkedHashMap<String, Int>? = null,
|
@ColumnInfo(name = "reactions") var reactions: LinkedHashMap<String, Int>? = null,
|
||||||
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
@ColumnInfo(name = "reactionsSelf") var reactionsSelf: ArrayList<String>? = null,
|
||||||
|
@ColumnInfo(name = "referenceId") var referenceId: String? = null,
|
||||||
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
@ColumnInfo(name = "systemMessage") var systemMessageType: ChatMessage.SystemMessageType,
|
||||||
@ColumnInfo(name = "timestamp") var timestamp: Long = 0
|
@ColumnInfo(name = "timestamp") var timestamp: Long = 0
|
||||||
// missing/not needed: referenceId
|
|
||||||
// missing/not needed: silent
|
// missing/not needed: silent
|
||||||
)
|
)
|
||||||
|
|
|
@ -48,6 +48,13 @@ object Migrations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val MIGRATION_12_13 = object : Migration(12, 13) {
|
||||||
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
|
Log.i("Migrations", "Migrating 12 to 13")
|
||||||
|
addReferenceIdToChatMessages(db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun migrateToRoom(db: SupportSQLiteDatabase) {
|
fun migrateToRoom(db: SupportSQLiteDatabase) {
|
||||||
db.execSQL(
|
db.execSQL(
|
||||||
"CREATE TABLE User_new (" +
|
"CREATE TABLE User_new (" +
|
||||||
|
@ -257,4 +264,15 @@ object Migrations {
|
||||||
Log.i("Migrations", "hasArchived already exists")
|
Log.i("Migrations", "hasArchived already exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addReferenceIdToChatMessages(db: SupportSQLiteDatabase) {
|
||||||
|
try {
|
||||||
|
db.execSQL(
|
||||||
|
"ALTER TABLE ChatMessages " +
|
||||||
|
"ADD COLUMN referenceId TEXT;"
|
||||||
|
)
|
||||||
|
} catch (e: SQLException) {
|
||||||
|
Log.i("Migrations", "Something went wrong when adding column referenceId to table ChatMessages")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ import java.util.Locale
|
||||||
ChatMessageEntity::class,
|
ChatMessageEntity::class,
|
||||||
ChatBlockEntity::class
|
ChatBlockEntity::class
|
||||||
],
|
],
|
||||||
version = 12,
|
version = 13,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration(from = 9, to = 11)
|
AutoMigration(from = 9, to = 11)
|
||||||
],
|
],
|
||||||
|
@ -114,7 +114,8 @@ abstract class TalkDatabase : RoomDatabase() {
|
||||||
Migrations.MIGRATION_7_8,
|
Migrations.MIGRATION_7_8,
|
||||||
Migrations.MIGRATION_8_9,
|
Migrations.MIGRATION_8_9,
|
||||||
Migrations.MIGRATION_10_11,
|
Migrations.MIGRATION_10_11,
|
||||||
Migrations.MIGRATION_11_12
|
Migrations.MIGRATION_11_12,
|
||||||
|
Migrations.MIGRATION_12_13
|
||||||
)
|
)
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.addCallback(
|
.addCallback(
|
||||||
|
@ -128,8 +129,8 @@ abstract class TalkDatabase : RoomDatabase() {
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCipherMigrationHook(): SQLiteDatabaseHook {
|
private fun getCipherMigrationHook(): SQLiteDatabaseHook =
|
||||||
return object : SQLiteDatabaseHook {
|
object : SQLiteDatabaseHook {
|
||||||
override fun preKey(database: SQLiteDatabase) {
|
override fun preKey(database: SQLiteDatabase) {
|
||||||
// unused atm
|
// unused atm
|
||||||
}
|
}
|
||||||
|
@ -140,6 +141,5 @@ abstract class TalkDatabase : RoomDatabase() {
|
||||||
Log.i(TAG, "DB cipher_migrate END")
|
Log.i(TAG, "DB cipher_migrate END")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,5 +42,6 @@ data class ChatMessageJson(
|
||||||
@JsonField(name = ["lastEditActorId"]) var lastEditActorId: String? = null,
|
@JsonField(name = ["lastEditActorId"]) var lastEditActorId: String? = null,
|
||||||
@JsonField(name = ["lastEditActorType"]) var lastEditActorType: String? = null,
|
@JsonField(name = ["lastEditActorType"]) var lastEditActorType: String? = null,
|
||||||
@JsonField(name = ["lastEditTimestamp"]) var lastEditTimestamp: Long? = 0,
|
@JsonField(name = ["lastEditTimestamp"]) var lastEditTimestamp: Long? = 0,
|
||||||
@JsonField(name = ["deleted"]) var deleted: Boolean = false
|
@JsonField(name = ["deleted"]) var deleted: Boolean = false,
|
||||||
|
@JsonField(name = ["referenceId"]) var referenceId: String? = null
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
|
@ -23,13 +23,14 @@ import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SYSTEM_NOTIFICATION_ID
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SYSTEM_NOTIFICATION_ID
|
||||||
|
import com.nextcloud.talk.utils.message.SendMessageUtils
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
@ -71,24 +72,31 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
sendDirectReply()
|
sendDirectReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMessageText(intent: Intent): CharSequence? {
|
private fun getMessageText(intent: Intent): CharSequence? =
|
||||||
return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(NotificationUtils.KEY_DIRECT_REPLY)
|
RemoteInput.getResultsFromIntent(intent)?.getCharSequence(NotificationUtils.KEY_DIRECT_REPLY)
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendDirectReply() {
|
private fun sendDirectReply() {
|
||||||
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
||||||
val apiVersion = ApiUtils.getChatApiVersion(currentUser.capabilities!!.spreedCapability!!, intArrayOf(1))
|
val apiVersion = ApiUtils.getChatApiVersion(currentUser.capabilities!!.spreedCapability!!, intArrayOf(1))
|
||||||
val url = ApiUtils.getUrlForChat(apiVersion, currentUser.baseUrl!!, roomToken!!)
|
val url = ApiUtils.getUrlForChat(apiVersion, currentUser.baseUrl!!, roomToken!!)
|
||||||
|
|
||||||
ncApi.sendChatMessage(credentials, url, replyMessage, currentUser.displayName, null, false)
|
ncApi.sendChatMessage(
|
||||||
|
credentials,
|
||||||
|
url,
|
||||||
|
replyMessage,
|
||||||
|
currentUser.displayName,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
SendMessageUtils().generateReferenceId() // TODO add temp chatMessage before with ref id...
|
||||||
|
)
|
||||||
?.subscribeOn(Schedulers.io())
|
?.subscribeOn(Schedulers.io())
|
||||||
?.observeOn(AndroidSchedulers.mainThread())
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
?.subscribe(object : Observer<GenericOverall> {
|
?.subscribe(object : Observer<ChatOverallSingleMessage> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
// unused atm
|
// unused atm
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(genericOverall: GenericOverall) {
|
override fun onNext(message: ChatOverallSingleMessage) {
|
||||||
confirmReplySent()
|
confirmReplySent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Nextcloud Talk - Android Client
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.utils.message
|
||||||
|
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class SendMessageUtils {
|
||||||
|
fun generateReferenceId(): String {
|
||||||
|
val randomString = UUID.randomUUID().toString()
|
||||||
|
val digest = MessageDigest.getInstance("SHA-256")
|
||||||
|
val hashBytes = digest.digest(randomString.toByteArray(Charsets.UTF_8))
|
||||||
|
return hashBytes.joinToString("") { "%02x".format(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = SendMessageUtils::class.java.simpleName
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue