diff --git a/lib/reducers/user-reducer.js b/lib/reducers/user-reducer.js --- a/lib/reducers/user-reducer.js +++ b/lib/reducers/user-reducer.js @@ -32,6 +32,7 @@ } from '../ops/user-store-ops.js'; import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js'; import { updateSpecs } from '../shared/updates/update-specs.js'; +import { processDMOpsActionType } from '../types/dm-ops.js'; import type { BaseAction } from '../types/redux-types.js'; import type { ClientUserInconsistencyReportCreationRequest } from '../types/report-types.js'; import { @@ -557,6 +558,28 @@ } return [{ userInfos: action.payload.users }, [], []]; + } else if (action.type === processDMOpsActionType) { + const newUserInfos = _keyBy(userInfo => userInfo.id)( + action.payload.userInfos, + ); + const ops = convertUserInfosToReplaceUserOps(newUserInfos); + const processedUserInfos: UserInfos = processUserStoreOps( + state.userInfos, + ops, + ); + + if (_isEqual(state.userInfos)(processedUserInfos)) { + return [state, [], []]; + } + + return [ + { + ...state, + userInfos: processedUserInfos, + }, + [], + ops, + ]; } return [state, [], []]; diff --git a/lib/shared/dm-ops/add-members-spec.js b/lib/shared/dm-ops/add-members-spec.js --- a/lib/shared/dm-ops/add-members-spec.js +++ b/lib/shared/dm-ops/add-members-spec.js @@ -72,6 +72,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } const currentThreadInfo: ThickRawThreadInfo = currentThreadInfoOptional; @@ -110,6 +111,7 @@ return { rawMessageInfos: [addMembersMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/change-relationship-spec.js b/lib/shared/dm-ops/change-relationship-spec.js new file mode 100644 --- /dev/null +++ b/lib/shared/dm-ops/change-relationship-spec.js @@ -0,0 +1,26 @@ +// @flow + +import type { DMOperationSpec } from './dm-op-spec.js'; +import type { + DMChangeRelationshipOperation, +} from '../../types/dm-ops.js'; +import type { ClientUpdateInfo } from '../../types/update-types.js'; + +const changeRelationshipSpec: DMOperationSpec = + Object.freeze({ + processDMOperation: async ( + dmOperation: DMChangeRelationshipOperation, + viewerID: string, + ) => { + const { editorID, userID, relationship } = dmOperation; + + const updateInfos: Array = []; + return { + rawMessageInfos: [], + updateInfos, + userInfos: {}, + }; + }, + }); + +export { changeRelationshipSpec }; diff --git a/lib/shared/dm-ops/change-thread-settings-spec.js b/lib/shared/dm-ops/change-thread-settings-spec.js --- a/lib/shared/dm-ops/change-thread-settings-spec.js +++ b/lib/shared/dm-ops/change-thread-settings-spec.js @@ -57,6 +57,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -96,6 +97,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -107,6 +109,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } changedFields.name = name; @@ -138,6 +141,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -155,6 +159,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -183,6 +188,7 @@ return { rawMessageInfos: generatedRawMessageInfos, updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/create-sidebar-spec.js b/lib/shared/dm-ops/create-sidebar-spec.js --- a/lib/shared/dm-ops/create-sidebar-spec.js +++ b/lib/shared/dm-ops/create-sidebar-spec.js @@ -101,6 +101,7 @@ return { rawMessageInfos: [], // included in updateInfos below updateInfos: [threadJoinUpdateInfo], + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/create-thread-spec.js b/lib/shared/dm-ops/create-thread-spec.js --- a/lib/shared/dm-ops/create-thread-spec.js +++ b/lib/shared/dm-ops/create-thread-spec.js @@ -170,6 +170,7 @@ return { rawMessageInfos: [], // included in updateInfos below updateInfos: [threadJoinUpdateInfo], + userInfos: {}, }; }, }); 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 @@ -1,6 +1,7 @@ // @flow import { addMembersSpec } from './add-members-spec.js'; +import { changeRelationshipSpec } from './change-relationship-spec.js'; import { changeThreadSettingsSpec } from './change-thread-settings-spec.js'; import { createSidebarSpec } from './create-sidebar-spec.js'; import { createThreadSpec } from './create-thread-spec.js'; @@ -26,4 +27,5 @@ [dmOperationTypes.LEAVE_THREAD]: leaveThreadSpec, [dmOperationTypes.REMOVE_MEMBERS]: removeMembersSpec, [dmOperationTypes.CHANGE_THREAD_SETTINGS]: changeThreadSettingsSpec, + [dmOperationTypes.CHANGE_RELATIONSHIP]: changeRelationshipSpec, }); diff --git a/lib/shared/dm-ops/join-thread-spec.js b/lib/shared/dm-ops/join-thread-spec.js --- a/lib/shared/dm-ops/join-thread-spec.js +++ b/lib/shared/dm-ops/join-thread-spec.js @@ -40,6 +40,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -68,6 +69,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } const currentThreadInfo: ThickRawThreadInfo = currentThreadInfoOptional; @@ -105,6 +107,7 @@ return { rawMessageInfos: [joinThreadMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/leave-thread-spec.js b/lib/shared/dm-ops/leave-thread-spec.js --- a/lib/shared/dm-ops/leave-thread-spec.js +++ b/lib/shared/dm-ops/leave-thread-spec.js @@ -27,6 +27,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } const threadInfo: ThickRawThreadInfo = threadInfoOptional; @@ -34,6 +35,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } @@ -69,6 +71,7 @@ return { rawMessageInfos: [leaveThreadMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/process-dm-ops.js b/lib/shared/dm-ops/process-dm-ops.js --- a/lib/shared/dm-ops/process-dm-ops.js +++ b/lib/shared/dm-ops/process-dm-ops.js @@ -37,7 +37,7 @@ console.log('ignored DMOperation because logged out'); return; } - const { rawMessageInfos, updateInfos } = await dmOpSpecs[ + const { rawMessageInfos, updateInfos, userInfos } = await dmOpSpecs[ dmOp.type ].processDMOperation(dmOp, viewerID, utilities); dispatch({ @@ -45,6 +45,7 @@ payload: { rawMessageInfos, updateInfos, + userInfos, }, }); }, diff --git a/lib/shared/dm-ops/remove-members-spec.js b/lib/shared/dm-ops/remove-members-spec.js --- a/lib/shared/dm-ops/remove-members-spec.js +++ b/lib/shared/dm-ops/remove-members-spec.js @@ -28,6 +28,7 @@ return { rawMessageInfos: [], updateInfos: [], + userInfos: {}, }; } const threadInfo: ThickRawThreadInfo = threadInfoOptional; @@ -68,6 +69,7 @@ return { rawMessageInfos: [removeMembersMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/send-edit-message-spec.js b/lib/shared/dm-ops/send-edit-message-spec.js --- a/lib/shared/dm-ops/send-edit-message-spec.js +++ b/lib/shared/dm-ops/send-edit-message-spec.js @@ -39,6 +39,7 @@ return { rawMessageInfos: [editMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/send-reaction-message-spec.js b/lib/shared/dm-ops/send-reaction-message-spec.js --- a/lib/shared/dm-ops/send-reaction-message-spec.js +++ b/lib/shared/dm-ops/send-reaction-message-spec.js @@ -47,6 +47,7 @@ return { rawMessageInfos: [reactionMessage], updateInfos, + userInfos: {}, }; }, }); diff --git a/lib/shared/dm-ops/send-text-message-spec.js b/lib/shared/dm-ops/send-text-message-spec.js --- a/lib/shared/dm-ops/send-text-message-spec.js +++ b/lib/shared/dm-ops/send-text-message-spec.js @@ -36,6 +36,7 @@ return { rawMessageInfos: [textMessage], updateInfos, + userInfos: {}, }; }, }); 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 @@ -12,6 +12,10 @@ rawMessageInfoValidator, } from './message-types.js'; import type { ThickRawThreadInfo } from './minimally-encoded-thread-permissions-types.js'; +import { + type TraditionalRelationshipAction, + traditionalRelationshipActionsList, +} from './relationship-types.js'; import { type NonSidebarThickThreadType, nonSidebarThickThreadTypes, @@ -22,6 +26,7 @@ import { threadInfoValidator } from '../permissions/minimally-encoded-thread-permissions-validators.js'; import { values } from '../utils/objects.js'; import { tShape, tString, tUserID } from '../utils/validation-utils.js'; +import type { UserInfos } from './user-types.js'; export const dmOperationTypes = Object.freeze({ CREATE_THREAD: 'create_thread', @@ -34,6 +39,7 @@ LEAVE_THREAD: 'leave_thread', REMOVE_MEMBERS: 'remove_members', CHANGE_THREAD_SETTINGS: 'change_thread_settings', + CHANGE_RELATIONSHIP: 'change_relationship', }); export type DMOperationType = $Values; @@ -249,6 +255,20 @@ rawEntryInfos: t.list(rawEntryInfoValidator), }); +export type DMChangeRelationshipOperation = { + +type: 'change_relationship', + +editorID: string, + +userID: string, + +relationship: TraditionalRelationshipAction, +}; +export const dmChangeRelationshipOperationValidator: TInterface = + tShape({ + type: tString(dmOperationTypes.CHANGE_RELATIONSHIP), + editorID: tUserID, + userID: tUserID, + relationship: t.enums.of(traditionalRelationshipActionsList), + }); + export type DMOperation = | DMCreateThreadOperation | DMCreateSidebarOperation @@ -259,7 +279,8 @@ | DMJoinThreadOperation | DMLeaveThreadOperation | DMRemoveMembersOperation - | DMChangeThreadSettingsOperation; + | DMChangeThreadSettingsOperation + | DMChangeRelationshipOperation; export const dmOperationValidator: TUnion = t.union([ dmCreateThreadOperationValidator, dmCreateSidebarOperationValidator, @@ -271,11 +292,13 @@ dmLeaveThreadOperationValidator, dmRemoveMembersOperationValidator, dmChangeThreadSettingsOperationValidator, + dmChangeRelationshipOperationValidator, ]); export type DMOperationResult = { rawMessageInfos: Array, updateInfos: Array, + userInfos: UserInfos, }; export const processDMOpsActionType = 'PROCESS_DM_OPS'; @@ -283,4 +306,5 @@ export type ProcessDMOpsPayload = { +rawMessageInfos: $ReadOnlyArray, +updateInfos: $ReadOnlyArray, + +userInfos: UserInfos, };