diff --git a/lib/shared/dm-ops/add-members-spec.js b/lib/shared/dm-ops/add-members-spec.js index 2dd0cc3d2..e44a74a0b 100644 --- a/lib/shared/dm-ops/add-members-spec.js +++ b/lib/shared/dm-ops/add-members-spec.js @@ -1,194 +1,193 @@ // @flow import invariant from 'invariant'; import uuid from 'uuid'; import { createRoleAndPermissionForThickThreads, createThickRawThreadInfo, } from './create-thread-spec.js'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMAddMembersOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { messageTruncationStatus, type RawMessageInfo, } from '../../types/message-types.js'; import { minimallyEncodeMemberInfo, type ThickRawThreadInfo, } from '../../types/minimally-encoded-thread-permissions-types.js'; import { joinThreadSubscription } from '../../types/subscription-types.js'; import type { ThickMemberInfo } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; import { values } from '../../utils/objects.js'; import { roleIsDefaultRole, userIsMember } from '../thread-utils.js'; function createAddNewMembersResults( dmOperation: DMAddMembersOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ): { +rawMessageInfos: Array, +updateInfos: Array, +threadInfo: ?ThickRawThreadInfo, } { const { editorID, time, messageID, addedUserIDs, existingThreadDetails } = dmOperation; const addMembersMessage = { type: messageTypes.ADD_MEMBERS, id: messageID, threadID: existingThreadDetails.threadID, creatorID: editorID, time, addedUserIDs: [...addedUserIDs], }; const viewerIsAdded = addedUserIDs.includes(viewerID); const updateInfos: Array = []; const rawMessageInfos: Array = []; let resultThreadInfo: ?ThickRawThreadInfo; if (viewerIsAdded) { const newThread = createThickRawThreadInfo( { ...existingThreadDetails, allMemberIDs: [...existingThreadDetails.allMemberIDs, ...addedUserIDs], }, viewerID, ); resultThreadInfo = newThread; updateInfos.push( { type: updateTypes.JOIN_THREAD, id: uuid.v4(), time, threadInfo: newThread, rawMessageInfos: [addMembersMessage], truncationStatus: messageTruncationStatus.EXHAUSTIVE, rawEntryInfos: [], }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID: existingThreadDetails.threadID, unread: true, }, ); - const repliesCountUpdate = createUpdateUnreadCountUpdate(newThread, [ + const repliesCountUpdate = createRepliesCountUpdate(newThread, [ addMembersMessage, ]); if ( repliesCountUpdate && repliesCountUpdate.type === updateTypes.UPDATE_THREAD ) { updateInfos.push(repliesCountUpdate); resultThreadInfo.repliesCount = repliesCountUpdate.threadInfo.repliesCount; } } else { const currentThreadInfoOptional = utilities.threadInfos[existingThreadDetails.threadID]; if (!currentThreadInfoOptional || !currentThreadInfoOptional.thick) { // We can't perform this operation now. It should be queued for later. return { rawMessageInfos: [], updateInfos: [], threadInfo: null, }; } const currentThreadInfo: ThickRawThreadInfo = currentThreadInfoOptional; const defaultRoleID = values(currentThreadInfo.roles).find(role => roleIsDefaultRole(role), )?.id; invariant(defaultRoleID, 'Default role ID must exist'); const { membershipPermissions } = createRoleAndPermissionForThickThreads( currentThreadInfo.type, currentThreadInfo.id, defaultRoleID, ); const newMembers = addedUserIDs .filter(userID => !userIsMember(currentThreadInfo, userID)) .map(userID => minimallyEncodeMemberInfo({ id: userID, role: defaultRoleID, permissions: membershipPermissions, isSender: editorID === viewerID, subscription: joinThreadSubscription, }), ); const newThreadInfo = { ...currentThreadInfo, members: [...currentThreadInfo.members, ...newMembers], }; resultThreadInfo = newThreadInfo; - const updateWithRepliesCount = createUpdateUnreadCountUpdate( - newThreadInfo, - [addMembersMessage], - ); + const updateWithRepliesCount = createRepliesCountUpdate(newThreadInfo, [ + addMembersMessage, + ]); updateInfos.push( updateWithRepliesCount ?? { type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: newThreadInfo, }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID: existingThreadDetails.threadID, unread: true, }, ); rawMessageInfos.push(addMembersMessage); } return { rawMessageInfos, updateInfos, threadInfo: resultThreadInfo, }; } const addMembersSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMAddMembersOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { rawMessageInfos, updateInfos } = createAddNewMembersResults( dmOperation, viewerID, utilities, ); return { rawMessageInfos, updateInfos }; }, canBeProcessed( dmOperation: DMAddMembersOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if ( utilities.threadInfos[dmOperation.existingThreadDetails.threadID] || dmOperation.addedUserIDs.includes(viewerID) ) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.existingThreadDetails.threadID, }, }; }, }); export { addMembersSpec, createAddNewMembersResults }; diff --git a/lib/shared/dm-ops/change-thread-settings-spec.js b/lib/shared/dm-ops/change-thread-settings-spec.js index 3aa9b68d5..1f313c97c 100644 --- a/lib/shared/dm-ops/change-thread-settings-spec.js +++ b/lib/shared/dm-ops/change-thread-settings-spec.js @@ -1,171 +1,171 @@ // @flow import invariant from 'invariant'; import uuid from 'uuid'; import { addMembersSpec, createAddNewMembersResults, } from './add-members-spec.js'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMChangeThreadSettingsOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import type { RawMessageInfo } from '../../types/message-types.js'; import type { RawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import type { LegacyRawThreadInfo } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; import { values } from '../../utils/objects.js'; function createAddMembersOperation( dmOperation: DMChangeThreadSettingsOperation, ) { const { editorID, time, messageIDsPrefix, changes, existingThreadDetails } = dmOperation; const newMemberIDs = changes.newMemberIDs && changes.newMemberIDs.length > 0 ? [...new Set(changes.newMemberIDs)] : []; return { type: 'add_members', editorID, time, messageID: `${messageIDsPrefix}/add_members`, addedUserIDs: newMemberIDs, existingThreadDetails, }; } const changeThreadSettingsSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMChangeThreadSettingsOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { editorID, time, changes, messageIDsPrefix, existingThreadDetails, } = dmOperation; const { name, description, color, avatar } = changes; const threadID = existingThreadDetails.threadID; let threadInfoToUpdate: ?(RawThreadInfo | LegacyRawThreadInfo) = utilities.threadInfos[threadID]; const updateInfos: Array = []; const rawMessageInfos: Array = []; if (changes.newMemberIDs && changes.newMemberIDs.length > 0) { const addMembersOperation = createAddMembersOperation(dmOperation); const addMembersResult = createAddNewMembersResults( addMembersOperation, viewerID, utilities, ); if (addMembersResult.threadInfo) { threadInfoToUpdate = addMembersResult.threadInfo; } updateInfos.push(...addMembersResult.updateInfos); rawMessageInfos.push(...addMembersResult.rawMessageInfos); } invariant(threadInfoToUpdate?.thick, 'Thread should be thick'); const changedFields: { [string]: string | number } = {}; if (name !== undefined && name !== null) { changedFields.name = name; threadInfoToUpdate = { ...threadInfoToUpdate, name, }; } if (description !== undefined && description !== null) { changedFields.description = description; threadInfoToUpdate = { ...threadInfoToUpdate, description, }; } if (color) { changedFields.color = color; threadInfoToUpdate = { ...threadInfoToUpdate, color, }; } if (avatar) { changedFields.avatar = JSON.stringify(avatar); threadInfoToUpdate = { ...threadInfoToUpdate, avatar, }; } for (const fieldName in changedFields) { const newValue = changedFields[fieldName]; rawMessageInfos.push({ type: messageTypes.CHANGE_SETTINGS, threadID, creatorID: editorID, time, field: fieldName, value: newValue, id: `${messageIDsPrefix}/${fieldName}`, }); } - const repliesCountUpdate = createUpdateUnreadCountUpdate( + const repliesCountUpdate = createRepliesCountUpdate( threadInfoToUpdate, rawMessageInfos, ); if (repliesCountUpdate) { updateInfos.push(repliesCountUpdate); } else if (values(changedFields).length > 0) { updateInfos.push({ type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: threadInfoToUpdate, }); } if (rawMessageInfos.length > 0) { updateInfos.push({ type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }); } return { rawMessageInfos, updateInfos, }; }, canBeProcessed( dmOperation: DMChangeThreadSettingsOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { return addMembersSpec.canBeProcessed( createAddMembersOperation(dmOperation), viewerID, utilities, ); }, }); export { changeThreadSettingsSpec }; diff --git a/lib/shared/dm-ops/dm-op-utils.js b/lib/shared/dm-ops/dm-op-utils.js index 4d619e85f..6e963875a 100644 --- a/lib/shared/dm-ops/dm-op-utils.js +++ b/lib/shared/dm-ops/dm-op-utils.js @@ -1,108 +1,108 @@ // @flow import uuid from 'uuid'; import type { AuxUserStore } from '../../types/aux-user-types.js'; import type { DMOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import type { RawMessageInfo } from '../../types/message-types.js'; import type { RawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import { outboundP2PMessageStatuses, type OutboundP2PMessage, } from '../../types/sqlite-types.js'; import { threadTypes } from '../../types/thread-types-enum.js'; import type { LegacyRawThreadInfo } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; import type { CurrentUserInfo } from '../../types/user-types.js'; import { getContentSigningKey } from '../../utils/crypto-utils.js'; import { values } from '../../utils/objects.js'; import { messageSpecs } from '../messages/message-specs.js'; function generateMessagesToPeers( message: DMOperation, peers: $ReadOnlyArray, userID: string, supportsAutoRetry: boolean, ): $ReadOnlyArray { const outboundP2PMessages = []; for (const peerID of peers) { const messageToPeer: OutboundP2PMessage = { messageID: uuid.v4(), deviceID: peerID, userID, timestamp: new Date().getTime().toString(), plaintext: JSON.stringify(message), ciphertext: '', status: outboundP2PMessageStatuses.persisted, supportsAutoRetry, }; outboundP2PMessages.push(messageToPeer); } return outboundP2PMessages; } export type DMOperationSpecification = { +op: DMOperation, +supportsAutoRetry: boolean, +recipients: 'all_peer_devices' | 'self_devices', }; async function createMessagesToPeersFromDMOp( operation: DMOperationSpecification, auxUserStore: AuxUserStore, currentUserInfo: ?CurrentUserInfo, ): Promise<$ReadOnlyArray> { if (!currentUserInfo?.id) { return []; } const selfDevices = auxUserStore.auxUserInfos[currentUserInfo.id].deviceList?.devices ?? []; const allPeerDevices = values(auxUserStore.auxUserInfos) .map(info => info.deviceList?.devices ?? []) .flat(); const devices = operation.recipients === 'all_peer_devices' ? allPeerDevices : selfDevices; const thisDeviceID = await getContentSigningKey(); const targetDevices = devices.filter(id => id !== thisDeviceID); return generateMessagesToPeers( operation.op, targetDevices, currentUserInfo.id, operation.supportsAutoRetry, ); } -function createUpdateUnreadCountUpdate( +function createRepliesCountUpdate( threadInfo: RawThreadInfo | LegacyRawThreadInfo, newMessages: $ReadOnlyArray, ): ?ClientUpdateInfo { if (threadInfo.type !== threadTypes.THICK_SIDEBAR) { return null; } const includedMessageTypes = new Set( Object.keys(messageTypes) .map(key => messageTypes[key]) .filter(type => messageSpecs[type].includedInRepliesCount), ); const filteredMessages = newMessages.filter(message => includedMessageTypes.has(message.type), ); const countIncrease = filteredMessages.length; if (countIncrease === 0) { return null; } const time = Math.max(...filteredMessages.map(message => message.time)); return { type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: { ...threadInfo, repliesCount: threadInfo.repliesCount + countIncrease, }, }; } -export { createMessagesToPeersFromDMOp, createUpdateUnreadCountUpdate }; +export { createMessagesToPeersFromDMOp, createRepliesCountUpdate }; diff --git a/lib/shared/dm-ops/join-thread-spec.js b/lib/shared/dm-ops/join-thread-spec.js index 85521bac0..be6cbd494 100644 --- a/lib/shared/dm-ops/join-thread-spec.js +++ b/lib/shared/dm-ops/join-thread-spec.js @@ -1,165 +1,165 @@ // @flow import invariant from 'invariant'; import uuid from 'uuid'; import { createRoleAndPermissionForThickThreads, createThickRawThreadInfo, } from './create-thread-spec.js'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMJoinThreadOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { messageTruncationStatus, type RawMessageInfo, } from '../../types/message-types.js'; import { minimallyEncodeMemberInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import { joinThreadSubscription } from '../../types/subscription-types.js'; import type { ThickMemberInfo } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; import { values } from '../../utils/objects.js'; import { roleIsDefaultRole, userIsMember } from '../thread-utils.js'; const joinThreadSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMJoinThreadOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { joinerID, time, messageID, existingThreadDetails } = dmOperation; const currentThreadInfo = utilities.threadInfos[existingThreadDetails.threadID]; const joinThreadMessage = { type: messageTypes.JOIN_THREAD, id: messageID, threadID: existingThreadDetails.threadID, creatorID: joinerID, time, }; if (userIsMember(currentThreadInfo, joinerID)) { return { rawMessageInfos: [joinThreadMessage], updateInfos: [ { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID: existingThreadDetails.threadID, unread: true, }, ], }; } const updateInfos: Array = []; const rawMessageInfos: Array = []; if (viewerID === joinerID) { const newThreadInfo = createThickRawThreadInfo( { ...existingThreadDetails, allMemberIDs: [...existingThreadDetails.allMemberIDs, joinerID], }, viewerID, ); updateInfos.push( { type: updateTypes.JOIN_THREAD, id: uuid.v4(), time, threadInfo: newThreadInfo, rawMessageInfos: [joinThreadMessage], truncationStatus: messageTruncationStatus.EXHAUSTIVE, rawEntryInfos: [], }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID: existingThreadDetails.threadID, unread: true, }, ); - const repliesCountUpdate = createUpdateUnreadCountUpdate(newThreadInfo, [ + const repliesCountUpdate = createRepliesCountUpdate(newThreadInfo, [ joinThreadMessage, ]); if (repliesCountUpdate) { updateInfos.push(repliesCountUpdate); } } else { invariant(currentThreadInfo.thick, 'Thread should be thick'); rawMessageInfos.push(joinThreadMessage); const defaultRoleID = values(currentThreadInfo.roles).find(role => roleIsDefaultRole(role), )?.id; invariant(defaultRoleID, 'Default role ID must exist'); const { membershipPermissions } = createRoleAndPermissionForThickThreads( currentThreadInfo.type, currentThreadInfo.id, defaultRoleID, ); const member = minimallyEncodeMemberInfo({ id: joinerID, role: defaultRoleID, permissions: membershipPermissions, isSender: joinerID === viewerID, subscription: joinThreadSubscription, }); const updatedThreadInfo = { ...currentThreadInfo, members: [...currentThreadInfo.members, member], }; - const updateWithRepliesCount = createUpdateUnreadCountUpdate( + const updateWithRepliesCount = createRepliesCountUpdate( updatedThreadInfo, [joinThreadMessage], ); updateInfos.push( updateWithRepliesCount ?? { type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: updatedThreadInfo, }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID: existingThreadDetails.threadID, unread: true, }, ); } return { rawMessageInfos, updateInfos, }; }, canBeProcessed( dmOperation: DMJoinThreadOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.existingThreadDetails.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.existingThreadDetails.threadID, }, }; }, }); export { joinThreadSpec }; diff --git a/lib/shared/dm-ops/leave-thread-spec.js b/lib/shared/dm-ops/leave-thread-spec.js index 495c478fe..0a0e527a7 100644 --- a/lib/shared/dm-ops/leave-thread-spec.js +++ b/lib/shared/dm-ops/leave-thread-spec.js @@ -1,100 +1,100 @@ // @flow import invariant from 'invariant'; import uuid from 'uuid'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMLeaveThreadOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { threadTypes } from '../../types/thread-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; import { userIsMember } from '../thread-utils.js'; const leaveThreadSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMLeaveThreadOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { editorID, time, messageID, threadID } = dmOperation; const threadInfo = utilities.threadInfos[threadID]; invariant(threadInfo.thick, 'Thread should be thick'); const leaveThreadMessage = { type: messageTypes.LEAVE_THREAD, id: messageID, threadID, creatorID: editorID, time, }; const updateInfos: Array = []; if ( viewerID === editorID && userIsMember(threadInfo, editorID) && (threadInfo.type !== threadTypes.THICK_SIDEBAR || (threadInfo.parentThreadID && !utilities.threadInfos[threadInfo.parentThreadID])) ) { updateInfos.push({ type: updateTypes.DELETE_THREAD, id: uuid.v4(), time, threadID, }); } else { const updatedThreadInfo = { ...threadInfo, members: threadInfo.members.filter(member => member.id !== editorID), }; - const updateWithRepliesCount = createUpdateUnreadCountUpdate( + const updateWithRepliesCount = createRepliesCountUpdate( updatedThreadInfo, [leaveThreadMessage], ); updateInfos.push( updateWithRepliesCount ?? { type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: updatedThreadInfo, }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }, ); } return { rawMessageInfos: [leaveThreadMessage], updateInfos, }; }, canBeProcessed( dmOperation: DMLeaveThreadOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.threadID, }, }; }, }); export { leaveThreadSpec }; diff --git a/lib/shared/dm-ops/remove-members-spec.js b/lib/shared/dm-ops/remove-members-spec.js index e7b39752a..6c5093912 100644 --- a/lib/shared/dm-ops/remove-members-spec.js +++ b/lib/shared/dm-ops/remove-members-spec.js @@ -1,104 +1,104 @@ // @flow import invariant from 'invariant'; import uuid from 'uuid'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMRemoveMembersOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { threadTypes } from '../../types/thread-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; const removeMembersSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMRemoveMembersOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { editorID, time, messageID, threadID, removedUserIDs } = dmOperation; const threadInfo = utilities.threadInfos[threadID]; invariant(threadInfo.thick, 'Thread should be thick'); const removeMembersMessage = { type: messageTypes.REMOVE_MEMBERS, id: messageID, threadID, time, creatorID: editorID, removedUserIDs: [...removedUserIDs], }; const removedUserIDsSet = new Set(removedUserIDs); const viewerIsRemoved = removedUserIDsSet.has(viewerID); const updateInfos: Array = []; if ( viewerIsRemoved && (threadInfo.type !== threadTypes.THICK_SIDEBAR || (threadInfo.parentThreadID && !utilities.threadInfos[threadInfo.parentThreadID])) ) { updateInfos.push({ type: updateTypes.DELETE_THREAD, id: uuid.v4(), time, threadID, }); } else { const updatedThreadInfo = { ...threadInfo, members: threadInfo.members.filter( member => !removedUserIDsSet.has(member.id), ), }; - const updateWithRepliesCount = createUpdateUnreadCountUpdate( + const updateWithRepliesCount = createRepliesCountUpdate( updatedThreadInfo, [removeMembersMessage], ); updateInfos.push( updateWithRepliesCount ?? { type: updateTypes.UPDATE_THREAD, id: uuid.v4(), time, threadInfo: updatedThreadInfo, }, { type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }, ); } return { rawMessageInfos: [removeMembersMessage], updateInfos, }; }, canBeProcessed( dmOperation: DMRemoveMembersOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.threadID, }, }; }, }); export { removeMembersSpec }; diff --git a/lib/shared/dm-ops/send-edit-message-spec.js b/lib/shared/dm-ops/send-edit-message-spec.js index 558413d37..d6fe83492 100644 --- a/lib/shared/dm-ops/send-edit-message-spec.js +++ b/lib/shared/dm-ops/send-edit-message-spec.js @@ -1,74 +1,74 @@ // @flow import uuid from 'uuid'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMSendEditMessageOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; const sendEditMessageSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMSendEditMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { threadID, creatorID, time, messageID, targetMessageID, text } = dmOperation; const editMessage = { type: messageTypes.EDIT_MESSAGE, id: messageID, threadID, creatorID, time, targetMessageID, text, }; const updateInfos: Array = []; if (creatorID !== viewerID) { updateInfos.push({ type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }); } const threadInfo = utilities.threadInfos[threadID]; - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [ editMessage, ]); if (repliesCountUpdate) { updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [editMessage], updateInfos, }; }, canBeProcessed( dmOperation: DMSendEditMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.threadID, }, }; }, }); export { sendEditMessageSpec }; diff --git a/lib/shared/dm-ops/send-reaction-message-spec.js b/lib/shared/dm-ops/send-reaction-message-spec.js index ef19112be..e0391a250 100644 --- a/lib/shared/dm-ops/send-reaction-message-spec.js +++ b/lib/shared/dm-ops/send-reaction-message-spec.js @@ -1,82 +1,82 @@ // @flow import uuid from 'uuid'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMSendReactionMessageOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; const sendReactionMessageSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMSendReactionMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { threadID, creatorID, time, messageID, targetMessageID, reaction, action, } = dmOperation; const reactionMessage = { type: messageTypes.REACTION, id: messageID, threadID, creatorID, time, targetMessageID, reaction, action, }; const updateInfos: Array = []; if (creatorID !== viewerID) { updateInfos.push({ type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }); } const threadInfo = utilities.threadInfos[threadID]; - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [ reactionMessage, ]); if (repliesCountUpdate) { updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [reactionMessage], updateInfos, }; }, canBeProcessed( dmOperation: DMSendReactionMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.threadID, }, }; }, }); export { sendReactionMessageSpec }; diff --git a/lib/shared/dm-ops/send-text-message-spec.js b/lib/shared/dm-ops/send-text-message-spec.js index faeef690b..c2b8c995a 100644 --- a/lib/shared/dm-ops/send-text-message-spec.js +++ b/lib/shared/dm-ops/send-text-message-spec.js @@ -1,71 +1,71 @@ // @flow import uuid from 'uuid'; import type { DMOperationSpec, ProcessDMOperationUtilities, } from './dm-op-spec.js'; -import { createUpdateUnreadCountUpdate } from './dm-op-utils.js'; +import { createRepliesCountUpdate } from './dm-op-utils.js'; import type { DMSendTextMessageOperation } from '../../types/dm-ops.js'; import { messageTypes } from '../../types/message-types-enum.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../../types/update-types.js'; const sendTextMessageSpec: DMOperationSpec = Object.freeze({ processDMOperation: async ( dmOperation: DMSendTextMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) => { const { threadID, creatorID, time, messageID, text } = dmOperation; const textMessage = { type: messageTypes.TEXT, id: messageID, threadID, creatorID, time, text, }; const updateInfos: Array = []; if (creatorID !== viewerID) { updateInfos.push({ type: updateTypes.UPDATE_THREAD_READ_STATUS, id: uuid.v4(), time, threadID, unread: true, }); } const threadInfo = utilities.threadInfos[threadID]; - const repliesCountUpdate = createUpdateUnreadCountUpdate(threadInfo, [ + const repliesCountUpdate = createRepliesCountUpdate(threadInfo, [ textMessage, ]); if (repliesCountUpdate) { updateInfos.push(repliesCountUpdate); } return { rawMessageInfos: [textMessage], updateInfos, }; }, canBeProcessed( dmOperation: DMSendTextMessageOperation, viewerID: string, utilities: ProcessDMOperationUtilities, ) { if (utilities.threadInfos[dmOperation.threadID]) { return { isProcessingPossible: true }; } return { isProcessingPossible: false, reason: { type: 'missing_thread', threadID: dmOperation.threadID, }, }; }, }); export { sendTextMessageSpec };