diff --git a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageTranslateDialog.vue b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageTranslateDialog.vue index 403b53b3e81..234cbc6dd22 100644 --- a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageTranslateDialog.vue +++ b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageTranslateDialog.vue @@ -91,7 +91,7 @@ import NcModal from '@nextcloud/vue/dist/Components/NcModal.js' import NcRichText from '@nextcloud/vue/dist/Components/NcRichText.js' import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' -import { getTranslationLanguages, translateText } from '../../../../../services/messagesService.js' +import { getTranslationLanguages, translateText } from '../../../../../services/translationService.js' export default { name: 'MessageTranslateDialog', diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/Reactions.spec.js b/src/components/MessagesList/MessagesGroup/Message/MessagePart/Reactions.spec.js index 5975bae6307..ef4617c2265 100644 --- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/Reactions.spec.js +++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/Reactions.spec.js @@ -16,13 +16,13 @@ import { addReactionToMessage, removeReactionFromMessage, getReactionsDetails, -} from '../../../../../services/messagesService.js' +} from '../../../../../services/reactionsService.ts' import vuexStore from '../../../../../store/index.js' import storeConfig from '../../../../../store/storeConfig.js' import { useReactionsStore } from '../../../../../stores/reactions.js' import { generateOCSResponse } from '../../../../../test-helpers.js' -jest.mock('../../../../../services/messagesService', () => ({ +jest.mock('../../../../../services/reactionsService', () => ({ getReactionsDetails: jest.fn(), addReactionToMessage: jest.fn(), removeReactionFromMessage: jest.fn(), diff --git a/src/deck.js b/src/deck.js index 3b348643c98..3d7ad268dad 100644 --- a/src/deck.js +++ b/src/deck.js @@ -28,7 +28,7 @@ import { showSuccess, showError } from '@nextcloud/dialogs' import { translate, translatePlural } from '@nextcloud/l10n' import { generateFilePath, generateUrl } from '@nextcloud/router' -import { postRichObjectToConversation } from './services/messagesService.js' +import { postRichObjectToConversation } from './services/messagesService.ts' import '@nextcloud/dialogs/style.css' diff --git a/src/maps.js b/src/maps.js index 6f42865ac78..07c475d16bf 100644 --- a/src/maps.js +++ b/src/maps.js @@ -28,7 +28,7 @@ import { showSuccess, showError } from '@nextcloud/dialogs' import { translate, translatePlural } from '@nextcloud/l10n' import { generateFilePath, generateUrl } from '@nextcloud/router' -import { postRichObjectToConversation } from './services/messagesService.js' +import { postRichObjectToConversation } from './services/messagesService.ts' import '@nextcloud/dialogs/style.css' diff --git a/src/services/messagesService.spec.js b/src/services/__tests__/messagesService.spec.js similarity index 97% rename from src/services/messagesService.spec.js rename to src/services/__tests__/messagesService.spec.js index 32fc33827fe..25f2eb4e030 100644 --- a/src/services/messagesService.spec.js +++ b/src/services/__tests__/messagesService.spec.js @@ -1,6 +1,7 @@ import axios from '@nextcloud/axios' import { generateOcsUrl } from '@nextcloud/router' +import { CHAT } from '../../constants.js' import { fetchMessages, getMessageContext, @@ -10,13 +11,16 @@ import { editMessage, postRichObjectToConversation, updateLastReadMessage, +} from '../messagesService.ts' +import { addReactionToMessage, removeReactionFromMessage, getReactionsDetails, +} from '../reactionsService.ts' +import { getTranslationLanguages, translateText, -} from './messagesService.js' -import { CHAT } from '../constants.js' +} from '../translationService.js' jest.mock('@nextcloud/axios', () => ({ get: jest.fn(), diff --git a/src/services/avatarService.ts b/src/services/avatarService.ts index d8000badce2..1c997e44745 100644 --- a/src/services/avatarService.ts +++ b/src/services/avatarService.ts @@ -46,7 +46,7 @@ const setConversationEmojiAvatar = async function(token: string, emoji: string, return axios.post(generateOcsUrl('apps/spreed/api/v1/room/{token}/avatar/emoji', { token }), { emoji, color, - } as setEmojiAvatarParams['params']) + } as setEmojiAvatarParams) } const deleteConversationAvatar = async function(token: string): deleteAvatarResponse { diff --git a/src/services/conversationsService.js b/src/services/conversationsService.js index 152aa0c1426..f1a93fdaa05 100644 --- a/src/services/conversationsService.js +++ b/src/services/conversationsService.js @@ -205,24 +205,6 @@ const deleteConversation = async function(token) { return axios.delete(generateOcsUrl('apps/spreed/api/v4/room/{token}', { token })) } -/** - * Clears the conversation history - * - * @param {string} token The token of the conversation to be deleted. - */ -const clearConversationHistory = async function(token) { - return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token })) -} - -/** - * Set conversation as unread - * - * @param {string} token The token of the conversation to be set as unread - */ -const setConversationUnread = async function(token) { - return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}/read', { token })) -} - /** * Add a conversation to the favorites * @@ -407,8 +389,6 @@ export { setConversationPassword, setConversationName, setConversationDescription, - clearConversationHistory, - setConversationUnread, setConversationPermissions, setCallPermissions, setMessageExpiration, diff --git a/src/services/messagesService.js b/src/services/messagesService.js deleted file mode 100644 index c86fadaf720..00000000000 --- a/src/services/messagesService.js +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @copyright Copyright (c) 2019 Marco Ambrosini - * - * @author Marco Ambrosini - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -import Hex from 'crypto-js/enc-hex.js' -import SHA256 from 'crypto-js/sha256.js' - -import axios from '@nextcloud/axios' -import { generateOcsUrl } from '@nextcloud/router' - -/** - * Fetches messages that belong to a particular conversation - * specified with its token. - * - * @param {object} data the wrapping object; - * @param {string} data.token the conversation token; - * @param {string} data.lastKnownMessageId last known message id; - * @param {boolean} data.includeLastKnown whether to include the last known message in the response; - * @param {number} [data.limit=100] Number of messages to load - * @param {object} options options; - */ -const fetchMessages = async function({ token, lastKnownMessageId, includeLastKnown, limit = 100 }, options) { - return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { - ...options, - params: { - setReadMarker: 0, - lookIntoFuture: 0, - lastKnownMessageId, - limit, - includeLastKnown: includeLastKnown ? 1 : 0, - }, - }) -} - -/** - * Fetches newly created messages that belong to a particular conversation - * specified with its token. - * - * @param {object} data the wrapping object; - * @param {number} data.lastKnownMessageId The id of the last message in the store. - * @param {string} data.token The conversation token; - * @param {number} [data.limit=100] Number of messages to load - * @param {object} options options - */ -const lookForNewMessages = async ({ token, lastKnownMessageId, limit = 100 }, options) => { - return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { - ...options, - params: { - setReadMarker: 0, - lookIntoFuture: 1, - lastKnownMessageId, - limit, - includeLastKnown: 0, - markNotificationsAsRead: 0, - }, - }) -} - -/** - * Get the context of a message - * - * Loads some messages from before and after the given one. - * - * @param {object} data the wrapping object; - * @param {string} data.token the conversation token; - * @param {number} data.messageId last known message id; - * @param {number} [data.limit=50] Number of messages to load - * @param {object} options options; - */ -const getMessageContext = async function({ token, messageId, limit = 50 }, options) { - return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{messageId}/context', { token, messageId }, options), { - ...options, - params: { - limit, - }, - }) -} - -/** - * Posts a new message to the server. - * - * @param {object} param0 The message object that is destructured - * @param {string} param0.token The conversation token - * @param {string} param0.message The message text - * @param {string} param0.actorDisplayName The display name of the actor - * @param {string} param0.referenceId A reference id to identify the message later again - * @param {object|undefined} param0.parent The message to be replied to - * @param {object} param1 options object destructured - * @param {boolean} param1.silent whether the message should trigger a notifications - */ -const postNewMessage = async function({ token, message, actorDisplayName, referenceId, parent }, { silent, ...options }) { - return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { - message, - actorDisplayName, - referenceId, - replyTo: parent?.id, - silent, - }, options) -} - -/** - * Deletes a message from the server. - * - * @param {object} param0 The message object that is destructured - * @param {string} param0.token The conversation token - * @param {string} param0.id The id of the message to be deleted - * @param {object} options request options - */ -const deleteMessage = async function({ token, id }, options) { - return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{id}', { token, id }, options), options) -} - -/** - * Edit a message text / file share caption. - * - * @param {object} param0 The destructured payload - * @param {string} param0.token The conversation token - * @param {string} param0.messageId The message id - * @param {string} param0.updatedMessage The modified text of the message / file share caption - * @param {object} options request options - */ -const editMessage = async function({ token, messageId, updatedMessage }, options) { - return axios.put(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{messageId}', { token, messageId }, options), { - message: updatedMessage, - }, options) -} - -/** - * Post a rich object to a conversation - * - * @param {string} token conversation token - * @param {object} data the wrapping object; - * @param {string} data.objectType object type - * @param {string} data.objectId object id - * @param {string} data.metaData JSON metadata of the rich object encoded as string - * @param {string} data.referenceId generated reference id, leave empty to generate it based on the other args - * @param {object} options request options - */ -const postRichObjectToConversation = async function(token, { objectType, objectId, metaData, referenceId }, options) { - if (!referenceId) { - const tempId = 'richobject-' + objectType + '-' + objectId + '-' + token + '-' + (new Date().getTime()) - referenceId = Hex.stringify(SHA256(tempId)) - } - return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}/share', { token }, options), { - objectType, - objectId, - metaData, - referenceId, - }, options) -} - -/** - * Updates the last read message id - * - * @param {string} token The token of the conversation to be removed from favorites - * @param {number} lastReadMessage id of the last read message to set - * @param {object} options request options - */ -const updateLastReadMessage = async function(token, lastReadMessage, options) { - return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}/read', { token }, options), { - lastReadMessage, - }, options) -} - -const addReactionToMessage = async function(token, messageId, selectedEmoji, options) { - return axios.post(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { token, messageId }, options), { - reaction: selectedEmoji, - }, options) -} - -const removeReactionFromMessage = async function(token, messageId, selectedEmoji, options) { - return axios.delete(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { token, messageId }, options), { - ...options, - params: { - reaction: selectedEmoji, - }, - }) -} - -const getReactionsDetails = async function(token, messageId, options) { - return axios.get(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { token, messageId }, options), options) -} - -const getTranslationLanguages = async function(options) { - return axios.get(generateOcsUrl('/translation/languages', undefined, options), options) -} - -const translateText = async function(text, fromLanguage, toLanguage, options) { - return axios.post(generateOcsUrl('/translation/translate', undefined, options), { - text, - fromLanguage, - toLanguage, - }, options) -} - -export { - fetchMessages, - lookForNewMessages, - getMessageContext, - postNewMessage, - deleteMessage, - postRichObjectToConversation, - updateLastReadMessage, - addReactionToMessage, - removeReactionFromMessage, - getReactionsDetails, - editMessage, - getTranslationLanguages, - translateText, -} diff --git a/src/services/messagesService.ts b/src/services/messagesService.ts new file mode 100644 index 00000000000..26bd9efec9a --- /dev/null +++ b/src/services/messagesService.ts @@ -0,0 +1,238 @@ +/** + * @copyright Copyright (c) 2019 Marco Ambrosini + * + * @author Marco Ambrosini + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +import Hex from 'crypto-js/enc-hex.js' +import SHA256 from 'crypto-js/sha256.js' + +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +import type { + ChatMessage, + clearHistoryResponse, + deleteMessageResponse, + editMessageParams, + editMessageResponse, + getMessageContextParams, + getMessageContextResponse, + markUnreadResponse, + postNewMessageParams, + postNewMessageResponse, + postRichObjectParams, + postRichObjectResponse, + receiveMessagesParams, + receiveMessagesResponse, + setReadMarkerParams, + setReadMarkerResponse +} from '../types' + +type ReceiveMessagesPayload = Partial & { token: string } +type GetMessageContextPayload = getMessageContextParams & { token: string, messageId: number } +type PostNewMessagePayload = Omit & { token: string, parent: ChatMessage } +type PostNewMessageOptions = Pick & object +type DeleteMessagePayload = { token: string, id: number } +type EditMessagePayload = { token: string, messageId: number, updatedMessage: editMessageParams['message'] } + +/** + * Fetches messages that belong to a particular conversation + * specified with its token. + * + * @param data the wrapping object; + * @param data.token the conversation token; + * @param data.lastKnownMessageId last known message id; + * @param data.includeLastKnown whether to include the last known message in the response; + * @param [data.limit=100] Number of messages to load + * @param options options; + */ +const fetchMessages = async function({ token, lastKnownMessageId, includeLastKnown, limit = 100 }: ReceiveMessagesPayload, options: object): receiveMessagesResponse { + return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { + ...options, + params: { + setReadMarker: 0, + lookIntoFuture: 0, + lastKnownMessageId, + limit, + includeLastKnown: includeLastKnown ? 1 : 0, + } as receiveMessagesParams, + }) +} + +/** + * Fetches newly created messages that belong to a particular conversation + * specified with its token. + * + * @param data the wrapping object; + * @param data.lastKnownMessageId The id of the last message in the store. + * @param data.token The conversation token; + * @param [data.limit=100] Number of messages to load + * @param options options + */ +const lookForNewMessages = async ({ token, lastKnownMessageId, limit = 100 }: ReceiveMessagesPayload, options: object): receiveMessagesResponse => { + return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { + ...options, + params: { + setReadMarker: 0, + lookIntoFuture: 1, + lastKnownMessageId, + limit, + includeLastKnown: 0, + markNotificationsAsRead: 0, + } as receiveMessagesParams, + }) +} + +/** + * Get the context of a message + * + * Loads some messages from before and after the given one. + * + * @param data the wrapping object; + * @param data.token the conversation token; + * @param data.messageId last known message id; + * @param [data.limit=50] Number of messages to load + * @param options options; + */ +const getMessageContext = async function({ token, messageId, limit = 50 }: GetMessageContextPayload, options: object): getMessageContextResponse { + return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{messageId}/context', { token, messageId }, options), { + ...options, + params: { + limit, + } as getMessageContextParams, + }) +} + +/** + * Posts a new message to the server. + * + * @param param0 The message object that is destructured + * @param param0.token The conversation token + * @param param0.message The message text + * @param param0.actorDisplayName The display name of the actor + * @param param0.referenceId A reference id to identify the message later again + * @param param0.parent The message to be replied to + * @param param1 options object destructured + * @param param1.silent whether the message should trigger a notifications + */ +const postNewMessage = async function({ token, message, actorDisplayName, referenceId, parent }: PostNewMessagePayload, { silent, ...options }: PostNewMessageOptions): postNewMessageResponse { + return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token }, options), { + message, + actorDisplayName, + referenceId, + replyTo: parent?.id, + silent, + } as postNewMessageParams, options) +} + +/** + * Clears the conversation history + * + * @param token The token of the conversation to be deleted. + */ +const clearConversationHistory = async function(token: string): clearHistoryResponse { + return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}', { token })) +} + +/** + * Deletes a message from the server. + * + * @param param0 The message object that is destructured + * @param param0.token The conversation token + * @param param0.id The id of the message to be deleted + * @param options request options + */ +const deleteMessage = async function({ token, id }: DeleteMessagePayload, options: object): deleteMessageResponse { + return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{id}', { token, id }, options), options) +} + +/** + * Edit a message text / file share caption. + * + * @param param0 The destructured payload + * @param param0.token The conversation token + * @param param0.messageId The message id + * @param param0.updatedMessage The modified text of the message / file share caption + * @param options request options + */ +const editMessage = async function({ token, messageId, updatedMessage }: EditMessagePayload, options: object): editMessageResponse { + return axios.put(generateOcsUrl('apps/spreed/api/v1/chat/{token}/{messageId}', { token, messageId }, options), { + message: updatedMessage, + } as editMessageParams, options) +} + +/** + * Post a rich object to a conversation + * + * @param token conversation token + * @param data the wrapping object; + * @param data.objectType object type + * @param data.objectId object id + * @param data.metaData JSON metadata of the rich object encoded as string + * @param data.referenceId generated reference id, leave empty to generate it based on the other args + * @param options request options + */ +const postRichObjectToConversation = async function(token: string, { objectType, objectId, metaData, referenceId }: postRichObjectParams, options: object): postRichObjectResponse { + if (!referenceId) { + const tempId = 'richobject-' + objectType + '-' + objectId + '-' + token + '-' + (new Date().getTime()) + referenceId = Hex.stringify(SHA256(tempId)) + } + return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}/share', { token }, options), { + objectType, + objectId, + metaData, + referenceId, + } as postRichObjectParams, options) +} + +/** + * Updates the last read message id + * + * @param token The token of the conversation to be removed from favorites + * @param lastReadMessage id of the last read message to set + * @param options request options + */ +const updateLastReadMessage = async function(token: string, lastReadMessage: setReadMarkerParams, options: object): setReadMarkerResponse { + return axios.post(generateOcsUrl('apps/spreed/api/v1/chat/{token}/read', { token }, options), { + lastReadMessage, + } as setReadMarkerParams, options) +} + +/** + * Set conversation as unread + * + * @param token The token of the conversation to be set as unread + */ +const setConversationUnread = async function(token: string): markUnreadResponse { + return axios.delete(generateOcsUrl('apps/spreed/api/v1/chat/{token}/read', { token })) +} + +export { + fetchMessages, + lookForNewMessages, + getMessageContext, + postNewMessage, + clearConversationHistory, + deleteMessage, + editMessage, + postRichObjectToConversation, + updateLastReadMessage, + setConversationUnread, +} diff --git a/src/services/reactionsService.ts b/src/services/reactionsService.ts new file mode 100644 index 00000000000..19cd2f7f0fa --- /dev/null +++ b/src/services/reactionsService.ts @@ -0,0 +1,63 @@ +/** + * @copyright Copyright (c) 2024 Maksim Sukharev + * + * @author Marco Ambrosini + * @author Maksim Sukharev + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +import type { + addReactionParams, + addReactionResponse, + deleteReactionParams, + deleteReactionResponse, + getReactionsResponse +} from '../types' + +const addReactionToMessage = async function(token: string, messageId: number, selectedEmoji: addReactionParams['reaction'], options: object): addReactionResponse { + return axios.post(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { + token, + messageId + }, options), { + reaction: selectedEmoji, + } as addReactionParams, options) +} + +const removeReactionFromMessage = async function(token: string, messageId: number, selectedEmoji: deleteReactionParams['reaction'], options: object): deleteReactionResponse { + return axios.delete(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { + token, + messageId + }, options), { + ...options, + params: { + reaction: selectedEmoji, + } as deleteReactionParams, + }) +} + +const getReactionsDetails = async function(token: string, messageId: number, options: object): getReactionsResponse { + return axios.get(generateOcsUrl('apps/spreed/api/v1/reaction/{token}/{messageId}', { + token, + messageId + }, options), options) +} + +export { addReactionToMessage, removeReactionFromMessage, getReactionsDetails } diff --git a/src/services/translationService.js b/src/services/translationService.js new file mode 100644 index 00000000000..b494cec2379 --- /dev/null +++ b/src/services/translationService.js @@ -0,0 +1,38 @@ +/** + * @copyright Copyright (c) 2024 Maksim Sukharev + * + * @author Maksim Sukharev + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +const getTranslationLanguages = async function(options) { + return axios.get(generateOcsUrl('/translation/languages', undefined, options), options) +} + +const translateText = async function(text, fromLanguage, toLanguage, options) { + return axios.post(generateOcsUrl('/translation/translate', undefined, options), { + text, + fromLanguage, + toLanguage, + }, options) +} + +export { getTranslationLanguages, translateText } diff --git a/src/store/conversationsStore.js b/src/store/conversationsStore.js index 147b5bf2933..b17014ad384 100644 --- a/src/store/conversationsStore.js +++ b/src/store/conversationsStore.js @@ -54,8 +54,6 @@ import { setConversationName, setConversationDescription, deleteConversation, - clearConversationHistory, - setConversationUnread, setNotificationLevel, setNotificationCalls, setConversationPermissions, @@ -63,6 +61,10 @@ import { setMessageExpiration, setConversationPassword, } from '../services/conversationsService.js' +import { + clearConversationHistory, + setConversationUnread, +} from '../services/messagesService.ts' import { startCallRecording, stopCallRecording, diff --git a/src/store/conversationsStore.spec.js b/src/store/conversationsStore.spec.js index 5e8d291661c..04ec957d39b 100644 --- a/src/store/conversationsStore.spec.js +++ b/src/store/conversationsStore.spec.js @@ -32,9 +32,8 @@ import { deleteConversation, setConversationPermissions, setCallPermissions, - setConversationUnread, } from '../services/conversationsService.js' -import { updateLastReadMessage } from '../services/messagesService.js' +import { updateLastReadMessage, setConversationUnread } from '../services/messagesService.ts' import { useTalkHashStore } from '../stores/talkHash.js' import { generateOCSErrorResponse, generateOCSResponse } from '../test-helpers.js' @@ -56,11 +55,11 @@ jest.mock('../services/conversationsService', () => ({ deleteConversation: jest.fn(), setConversationPermissions: jest.fn(), setCallPermissions: jest.fn(), - setConversationUnread: jest.fn(), })) jest.mock('../services/messagesService', () => ({ updateLastReadMessage: jest.fn(), + setConversationUnread: jest.fn(), })) jest.mock('@nextcloud/event-bus') diff --git a/src/store/messagesStore.js b/src/store/messagesStore.js index bf1e62c7eab..b9d8b3895ee 100644 --- a/src/store/messagesStore.js +++ b/src/store/messagesStore.js @@ -43,7 +43,7 @@ import { getMessageContext, postNewMessage, postRichObjectToConversation, -} from '../services/messagesService.js' +} from '../services/messagesService.ts' import { useChatExtrasStore } from '../stores/chatExtras.js' import { useGuestNameStore } from '../stores/guestName.js' import { useReactionsStore } from '../stores/reactions.js' diff --git a/src/store/messagesStore.spec.js b/src/store/messagesStore.spec.js index 75f593f4f54..de5347f7874 100644 --- a/src/store/messagesStore.spec.js +++ b/src/store/messagesStore.spec.js @@ -23,7 +23,7 @@ import { lookForNewMessages, postNewMessage, postRichObjectToConversation, -} from '../services/messagesService.js' +} from '../services/messagesService.ts' import { useChatExtrasStore } from '../stores/chatExtras.js' import { useGuestNameStore } from '../stores/guestName.js' import { useReactionsStore } from '../stores/reactions.js' diff --git a/src/stores/__tests__/reactions.spec.js b/src/stores/__tests__/reactions.spec.js index c41b49efdc3..faf917318a8 100644 --- a/src/stores/__tests__/reactions.spec.js +++ b/src/stores/__tests__/reactions.spec.js @@ -4,12 +4,12 @@ import Vuex from 'vuex' import { showError } from '@nextcloud/dialogs' -import { getReactionsDetails, addReactionToMessage, removeReactionFromMessage } from '../../services/messagesService.js' +import { getReactionsDetails, addReactionToMessage, removeReactionFromMessage } from '../../services/reactionsService.ts' import vuexStore from '../../store/index.js' import { generateOCSErrorResponse, generateOCSResponse } from '../../test-helpers.js' import { useReactionsStore } from '../reactions.js' -jest.mock('../../services/messagesService', () => ({ +jest.mock('../../services/reactionsService', () => ({ getReactionsDetails: jest.fn(), addReactionToMessage: jest.fn(), removeReactionFromMessage: jest.fn(), diff --git a/src/stores/reactions.js b/src/stores/reactions.js index 58606b92209..7fcbb53e162 100644 --- a/src/stores/reactions.js +++ b/src/stores/reactions.js @@ -30,7 +30,7 @@ import { getReactionsDetails, addReactionToMessage, removeReactionFromMessage, -} from '../services/messagesService.js' +} from '../services/reactionsService.ts' import store from '../store/index.js' /** diff --git a/src/types/index.ts b/src/types/index.ts index 7459dccf78f..ad005697aec 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -12,12 +12,9 @@ type NotificationAction = { primary: boolean, } -type ParamObject = { - id: string, - name: string, - type: string, -} -export type Notification>> = { +type RichObjectParameter = components['schemas']['RichObjectParameter'] +type RichObject = Pick +export type Notification>> = { notificationId: number, app: string, user: string, @@ -40,30 +37,33 @@ export type Notification +export type File = RichObject<'size'|'path'|'link'|'mimetype'|'preview-available'> & { 'etag': string, 'permissions': number, - 'mimetype': string, - 'preview-available': string, 'width': number, 'height': number, } -type MessageParameters = Record -export type ChatMessage = Omit & { - messageParameters: MessageParameters -} +export type ChatMessage = components['schemas']['ChatMessageWithParent'] +export type receiveMessagesParams = ApiOptions['params'] +export type receiveMessagesResponse = ApiResponse +export type getMessageContextParams = ApiOptions['params'] +export type getMessageContextResponse = ApiResponse +export type postNewMessageParams = ApiOptions['params'] +export type postNewMessageResponse = ApiResponse +export type clearHistoryResponse = ApiResponse +export type deleteMessageResponse = ApiResponse +export type editMessageParams = ApiOptions['params'] +export type editMessageResponse = ApiResponse +export type postRichObjectParams = ApiOptions['params'] +export type postRichObjectResponse = ApiResponse +export type setReadMarkerParams = ApiOptions['params'] +export type setReadMarkerResponse = ApiResponse +export type markUnreadResponse = ApiResponse // Avatars export type setFileAvatarResponse = ApiResponse -export type setEmojiAvatarParams = ApiOptions +export type setEmojiAvatarParams = ApiOptions['params'] export type setEmojiAvatarResponse = ApiResponse export type deleteAvatarResponse = ApiResponse @@ -79,12 +79,20 @@ export type disableBotResponse = ApiResponse, + roomName: RichObject, + remoteServer: RichObject, } export type NotificationInvite = Notification export type getSharesResponse = ApiResponse export type acceptShareResponse = ApiResponse export type rejectShareResponse = ApiResponse + +// Reactions +export type getReactionsParams = ApiOptions['params'] +export type getReactionsResponse = ApiResponse +export type addReactionParams = ApiOptions['params'] +export type addReactionResponse = ApiResponse +export type deleteReactionParams = ApiOptions['params'] +export type deleteReactionResponse = ApiResponse diff --git a/src/types/vendor/crypto-js.d.ts b/src/types/vendor/crypto-js.d.ts new file mode 100644 index 00000000000..e54b995416a --- /dev/null +++ b/src/types/vendor/crypto-js.d.ts @@ -0,0 +1 @@ +declare module 'crypto-js/*.js' diff --git a/src/utils/getItemTypeFromMessage.ts b/src/utils/getItemTypeFromMessage.ts index 94cef7ea2b8..67a31b24622 100644 --- a/src/utils/getItemTypeFromMessage.ts +++ b/src/utils/getItemTypeFromMessage.ts @@ -1,5 +1,5 @@ import { SHARED_ITEM } from '../constants.js' -import type { ChatMessage, File } from '../types' +import type { ChatMessage } from '../types' export const getItemTypeFromMessage = function(message: ChatMessage): string { if (message.messageParameters?.object) { @@ -13,8 +13,8 @@ export const getItemTypeFromMessage = function(message: ChatMessage): string { return SHARED_ITEM.TYPES.OTHER } } else if (message.messageParameters?.file) { - const messageType = message.messageType || '' - const mimetype = (message.messageParameters.file as File)?.mimetype || '' + const messageType = message.messageType + const mimetype = message.messageParameters.file.mimetype || '' if (messageType === 'record-audio' || messageType === 'record-video') { return SHARED_ITEM.TYPES.RECORDING } else if (messageType === 'voice-message') {