diff --git a/lib/shared/dm-ops/dm-op-specs.js b/lib/shared/dm-ops/dm-op-specs.js --- a/lib/shared/dm-ops/dm-op-specs.js +++ b/lib/shared/dm-ops/dm-op-specs.js @@ -5,6 +5,7 @@ import { createThreadSpec } from './create-thread-spec.js'; import type { DMOperationSpec } from './dm-op-spec.js'; import { joinThreadSpec } from './join-thread-spec.js'; +import { leaveThreadSpec } from './leave-thread-spec.js'; import { sendEditMessageSpec } from './send-edit-message-spec.js'; import { sendReactionMessageSpec } from './send-reaction-message-spec.js'; import { sendTextMessageSpec } from './send-text-message-spec.js'; @@ -20,4 +21,5 @@ [dmOperationTypes.SEND_EDIT_MESSAGE]: sendEditMessageSpec, [dmOperationTypes.ADD_MEMBERS]: addMembersSpec, [dmOperationTypes.JOIN_THREAD]: joinThreadSpec, + [dmOperationTypes.LEAVE_THREAD]: leaveThreadSpec, }); diff --git a/lib/shared/dm-ops/leave-thread-spec.js b/lib/shared/dm-ops/leave-thread-spec.js new file mode 100644 --- /dev/null +++ b/lib/shared/dm-ops/leave-thread-spec.js @@ -0,0 +1,86 @@ +// @flow + +import uuid from 'uuid'; + +import type { + DMOperationSpec, + ProcessDMOperationUtilities, +} from './dm-op-spec.js'; +import type { DMLeaveThreadOperation } from '../../types/dm-ops.js'; +import { messageTypes } from '../../types/message-types-enum.js'; +import type { ThickRawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.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 threadInfoOptional = utilities.threadInfos[threadID]; + if (!threadInfoOptional || !threadInfoOptional.thick) { + // We can't perform this operation now. It should be queued for later. + return { + rawMessageInfos: [], + updateInfos: [], + }; + } + const threadInfo: ThickRawThreadInfo = threadInfoOptional; + + 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), + }; + updateInfos.push( + { + 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, + }; + }, +}); + +export { leaveThreadSpec }; diff --git a/lib/types/dm-ops.js b/lib/types/dm-ops.js --- a/lib/types/dm-ops.js +++ b/lib/types/dm-ops.js @@ -23,6 +23,7 @@ SEND_EDIT_MESSAGE: 'send_edit_message', ADD_MEMBERS: 'add_members', JOIN_THREAD: 'join_thread', + LEAVE_THREAD: 'leave_thread', }); export type DMOperationType = $Values; @@ -206,6 +207,22 @@ existingThreadDetails: createThickRawThreadInfoInputValidator, }); +export type DMLeaveThreadOperation = { + +type: 'leave_thread', + +editorID: string, + +time: number, + +messageID: string, + +threadID: string, +}; +export const dmLeaveThreadOperationValidator: TInterface = + tShape({ + type: tString(dmOperationTypes.LEAVE_THREAD), + editorID: tUserID, + time: t.Number, + messageID: t.String, + threadID: t.String, + }); + export type DMOperation = | DMCreateThreadOperation | DMCreateSidebarOperation @@ -213,7 +230,8 @@ | DMSendReactionMessageOperation | DMSendEditMessageOperation | DMAddMembersOperation - | DMJoinThreadOperation; + | DMJoinThreadOperation + | DMLeaveThreadOperation; export const dmOperationValidator: TUnion = t.union([ dmCreateThreadOperationValidator, dmCreateSidebarOperationValidator, @@ -222,6 +240,7 @@ dmSendEditMessageOperationValidator, dmAddMembersOperationValidator, dmJoinThreadOperationValidator, + dmLeaveThreadOperationValidator, ]); export type DMOperationResult = {