diff --git a/lib/ops/thread-store-ops.js b/lib/ops/thread-store-ops.js --- a/lib/ops/thread-store-ops.js +++ b/lib/ops/thread-store-ops.js @@ -1,10 +1,10 @@ // @flow import { type BaseStoreOpsHandlers } from './base-ops.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { ClientDBThreadInfo, - RawThreadInfo, - RawThreadInfos, + MinimallyEncodedRawThreadInfos, ThreadStore, } from '../types/thread-types.js'; import { @@ -23,7 +23,7 @@ export type ReplaceThreadOperation = { +type: 'replace', - +payload: { +id: string, +threadInfo: RawThreadInfo }, + +payload: { +id: string, +threadInfo: MinimallyEncodedRawThreadInfo }, }; export type ThreadStoreOperation = @@ -45,7 +45,7 @@ ThreadStore, ThreadStoreOperation, ClientDBThreadStoreOperation, - RawThreadInfos, + MinimallyEncodedRawThreadInfos, ClientDBThreadInfo, > = { processStoreOperations( @@ -87,7 +87,7 @@ }, translateClientDBData(data: $ReadOnlyArray): { - +[id: string]: RawThreadInfo, + +[id: string]: MinimallyEncodedRawThreadInfo, } { return Object.fromEntries( data.map((dbThreadInfo: ClientDBThreadInfo) => [ diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js --- a/lib/reducers/thread-reducer.js +++ b/lib/reducers/thread-reducer.js @@ -1,5 +1,7 @@ // @flow +import invariant from 'invariant'; + import { setThreadUnreadStatusActionTypes, updateActivityActionTypes, @@ -31,6 +33,7 @@ } from '../ops/thread-store-ops.js'; import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js'; import { updateSpecs } from '../shared/updates/update-specs.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { BaseAction } from '../types/redux-types.js'; import { type ClientThreadInconsistencyReportCreationRequest } from '../types/report-types.js'; import { @@ -42,8 +45,7 @@ incrementalStateSyncActionType, } from '../types/socket-types.js'; import type { - RawThreadInfo, - RawThreadInfos, + MinimallyEncodedRawThreadInfos, ThreadStore, } from '../types/thread-types.js'; import { @@ -56,7 +58,7 @@ threadStoreOpsHandlers; function generateOpsForThreadUpdates( - threadInfos: RawThreadInfos, + threadInfos: MinimallyEncodedRawThreadInfos, payload: { +updatesResult: { +newUpdates: $ReadOnlyArray, ... }, ... @@ -92,10 +94,16 @@ { type: 'remove_all', }, - ...Object.keys(newThreadInfos).map((id: string) => ({ - type: 'replace', - payload: { id, threadInfo: newThreadInfos[id] }, - })), + ...Object.keys(newThreadInfos).map((id: string) => { + invariant( + newThreadInfos[id].minimallyEncoded, + 'newThreadInfos must be minimallyEncoded for current clients', + ); + return { + type: 'replace', + payload: { id, threadInfo: newThreadInfos[id] }, + }; + }), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -170,60 +178,31 @@ } else if (action.type === updateSubscriptionActionTypes.success) { const { threadID, subscription } = action.payload; const threadInfo = state.threadInfos[threadID]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (threadInfo.minimallyEncoded) { - const newThreadInfo = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - subscription, - }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: newThreadInfo, - }, - }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } else { - const newThreadInfo = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - subscription, - }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: newThreadInfo, - }, + const newThreadInfo = { + ...threadInfo, + currentUser: { + ...threadInfo.currentUser, + subscription, + }, + }; + const threadStoreOperations = [ + { + type: 'replace', + payload: { + id: threadID, + threadInfo: newThreadInfo, }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } + }, + ]; + const updatedThreadStore = processThreadStoreOperations( + state, + threadStoreOperations, + ); + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; } else if (action.type === saveMessagesActionType) { const threadIDToMostRecentTime = new Map(); for (const messageInfo of action.payload.rawMessageInfos) { @@ -232,7 +211,7 @@ threadIDToMostRecentTime.set(messageInfo.threadID, messageInfo.time); } } - const changedThreadInfos: { [string]: RawThreadInfo } = {}; + const changedThreadInfos: { [string]: MinimallyEncodedRawThreadInfo } = {}; for (const [threadID, mostRecentTime] of threadIDToMostRecentTime) { const threadInfo = state.threadInfos[threadID]; if ( @@ -243,24 +222,14 @@ continue; } const changedThreadInfo = state.threadInfos[threadID]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (changedThreadInfo.minimallyEncoded) { - changedThreadInfos[threadID] = { - ...changedThreadInfo, - currentUser: { - ...changedThreadInfo.currentUser, - unread: true, - }, - }; - } else { - changedThreadInfos[threadID] = { - ...changedThreadInfo, - currentUser: { - ...changedThreadInfo.currentUser, - unread: true, - }, - }; - } + + changedThreadInfos[threadID] = { + ...changedThreadInfo, + currentUser: { + ...changedThreadInfo.currentUser, + unread: true, + }, + }; } if (Object.keys(changedThreadInfos).length !== 0) { const threadStoreOperations = Object.keys(changedThreadInfos).map(id => ({ @@ -303,6 +272,10 @@ const threadStoreOperations: ThreadStoreOperation[] = []; if (rawThreadInfos) { for (const rawThreadInfo of rawThreadInfos) { + invariant( + rawThreadInfo.minimallyEncoded, + 'rawThreadInfo must be minimallyEncoded on new clients', + ); threadStoreOperations.push({ type: 'replace', payload: { @@ -339,33 +312,19 @@ threadStoreOperations, }; } else if (action.type === updateActivityActionTypes.success) { - const updatedThreadInfos: { [string]: RawThreadInfo } = {}; + const updatedThreadInfos: { [string]: MinimallyEncodedRawThreadInfo } = {}; for (const setToUnread of action.payload.result.unfocusedToUnread) { const threadInfo = state.threadInfos[setToUnread]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (threadInfo.minimallyEncoded) { - if (threadInfo && !threadInfo.currentUser.unread) { - updatedThreadInfos[setToUnread] = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - unread: true, - }, - }; - } - } else { - if (threadInfo && !threadInfo.currentUser.unread) { - updatedThreadInfos[setToUnread] = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - unread: true, - }, - }; - } + if (threadInfo && !threadInfo.currentUser.unread) { + updatedThreadInfos[setToUnread] = { + ...threadInfo, + currentUser: { + ...threadInfo.currentUser, + unread: true, + }, + }; } } - if (Object.keys(updatedThreadInfos).length === 0) { return { threadStore: state, @@ -392,60 +351,31 @@ } else if (action.type === setThreadUnreadStatusActionTypes.started) { const { threadID, unread } = action.payload; const threadInfo = state.threadInfos[threadID]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (threadInfo.minimallyEncoded) { - const updatedThreadInfo = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - unread, - }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThreadInfo, - }, - }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } else { - const updatedThreadInfo = { - ...threadInfo, - currentUser: { - ...threadInfo.currentUser, - unread, - }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThreadInfo, - }, + const updatedThreadInfo = { + ...threadInfo, + currentUser: { + ...threadInfo.currentUser, + unread, + }, + }; + const threadStoreOperations = [ + { + type: 'replace', + payload: { + id: threadID, + threadInfo: updatedThreadInfo, }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } + }, + ]; + const updatedThreadStore = processThreadStoreOperations( + state, + threadStoreOperations, + ); + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; } else if (action.type === setThreadUnreadStatusActionTypes.success) { const { threadID, resetToUnread } = action.payload; const currentUser = state.threadInfos[threadID].currentUser; @@ -459,54 +389,28 @@ } const threadInfo = state.threadInfos[threadID]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (threadInfo.minimallyEncoded) { - const updatedThread = { - ...threadInfo, - currentUser: { ...threadInfo.currentUser, unread: true }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThread, - }, - }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } else { - const updatedThread = { - ...threadInfo, - currentUser: { ...threadInfo.currentUser, unread: true }, - }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThread, - }, + const updatedThread = { + ...threadInfo, + currentUser: { ...threadInfo.currentUser, unread: true }, + }; + const threadStoreOperations = [ + { + type: 'replace', + payload: { + id: threadID, + threadInfo: updatedThread, }, - ]; - const updatedThreadStore = processThreadStoreOperations( - state, - threadStoreOperations, - ); - return { - threadStore: updatedThreadStore, - newThreadInconsistencies: [], - threadStoreOperations, - }; - } + }, + ]; + const updatedThreadStore = processThreadStoreOperations( + state, + threadStoreOperations, + ); + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; } else if (action.type === setClientDBStoreActionType) { return { threadStore: action.payload.threadStore ?? state, diff --git a/lib/shared/updates/delete-account-spec.js b/lib/shared/updates/delete-account-spec.js --- a/lib/shared/updates/delete-account-spec.js +++ b/lib/shared/updates/delete-account-spec.js @@ -3,7 +3,7 @@ import t from 'tcomb'; import type { UpdateSpec } from './update-spec.js'; -import type { RawThreadInfos } from '../../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { AccountDeletionRawUpdateInfo, @@ -19,49 +19,31 @@ AccountDeletionUpdateData, > = Object.freeze({ generateOpsForThreadUpdates( - storeThreadInfos: RawThreadInfos, + storeThreadInfos: MinimallyEncodedRawThreadInfos, update: AccountDeletionUpdateInfo, ) { const operations = []; for (const threadID in storeThreadInfos) { const threadInfo = storeThreadInfos[threadID]; - // TODO (atul): Try to get rid of this ridiculous branching. - if (threadInfo.minimallyEncoded) { - const newMembers = threadInfo.members.filter( - member => member.id !== update.deletedUserID, - ); - if (newMembers.length < threadInfo.members.length) { - const updatedThread = { - ...threadInfo, - members: newMembers, - }; - operations.push({ - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThread, - }, - }); - } - } else { - const newMembers = threadInfo.members.filter( - member => member.id !== update.deletedUserID, - ); - if (newMembers.length < threadInfo.members.length) { - const updatedThread = { - ...threadInfo, - members: newMembers, - }; - operations.push({ - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThread, - }, - }); - } + + const newMembers = threadInfo.members.filter( + member => member.id !== update.deletedUserID, + ); + if (newMembers.length < threadInfo.members.length) { + const updatedThread = { + ...threadInfo, + members: newMembers, + }; + operations.push({ + type: 'replace', + payload: { + id: threadID, + threadInfo: updatedThread, + }, + }); } } + return operations; }, reduceUserInfos(state: UserInfos, update: AccountDeletionUpdateInfo) { diff --git a/lib/shared/updates/join-thread-spec.js b/lib/shared/updates/join-thread-spec.js --- a/lib/shared/updates/join-thread-spec.js +++ b/lib/shared/updates/join-thread-spec.js @@ -18,7 +18,7 @@ messageTruncationStatusValidator, rawMessageInfoValidator, } from '../../types/message-types.js'; -import { type RawThreadInfos } from '../../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ThreadJoinUpdateInfo, @@ -35,12 +35,16 @@ ThreadJoinUpdateData, > = Object.freeze({ generateOpsForThreadUpdates( - storeThreadInfos: RawThreadInfos, + storeThreadInfos: MinimallyEncodedRawThreadInfos, update: ThreadJoinUpdateInfo, ) { if (_isEqual(storeThreadInfos[update.threadInfo.id])(update.threadInfo)) { return null; } + invariant( + update.threadInfo.minimallyEncoded, + 'update threadInfo must be minimallyEncoded', + ); return [ { type: 'replace', diff --git a/lib/shared/updates/update-spec.js b/lib/shared/updates/update-spec.js --- a/lib/shared/updates/update-spec.js +++ b/lib/shared/updates/update-spec.js @@ -14,7 +14,10 @@ MessageTruncationStatuses, FetchMessageInfosResult, } from '../../types/message-types.js'; -import type { RawThreadInfos } from '../../types/thread-types.js'; +import type { + MinimallyEncodedRawThreadInfos, + RawThreadInfos, +} from '../../types/thread-types.js'; import type { UpdateType } from '../../types/update-types-enum.js'; import type { ClientUpdateInfo, @@ -54,7 +57,7 @@ Data: UpdateData, > = { +generateOpsForThreadUpdates?: ( - storeThreadInfos: RawThreadInfos, + storeThreadInfos: MinimallyEncodedRawThreadInfos, update: UpdateInfo, ) => ?$ReadOnlyArray, +mergeEntryInfos?: ( diff --git a/lib/shared/updates/update-thread-read-status-spec.js b/lib/shared/updates/update-thread-read-status-spec.js --- a/lib/shared/updates/update-thread-read-status-spec.js +++ b/lib/shared/updates/update-thread-read-status-spec.js @@ -3,7 +3,7 @@ import t from 'tcomb'; import type { UpdateSpec } from './update-spec.js'; -import type { RawThreadInfos } from '../../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ThreadReadStatusUpdateInfo, @@ -18,7 +18,7 @@ ThreadReadStatusUpdateData, > = Object.freeze({ generateOpsForThreadUpdates( - storeThreadInfos: RawThreadInfos, + storeThreadInfos: MinimallyEncodedRawThreadInfos, update: ThreadReadStatusUpdateInfo, ) { if ( diff --git a/lib/shared/updates/update-thread-spec.js b/lib/shared/updates/update-thread-spec.js --- a/lib/shared/updates/update-thread-spec.js +++ b/lib/shared/updates/update-thread-spec.js @@ -1,11 +1,12 @@ // @flow +import invariant from 'invariant'; import _isEqual from 'lodash/fp/isEqual.js'; import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; import { rawThreadInfoValidator } from '../../permissions/minimally-encoded-thread-permissions-validators.js'; -import { type RawThreadInfos } from '../../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { ThreadUpdateInfo, @@ -21,12 +22,16 @@ ThreadUpdateData, > = Object.freeze({ generateOpsForThreadUpdates( - storeThreadInfos: RawThreadInfos, + storeThreadInfos: MinimallyEncodedRawThreadInfos, update: ThreadUpdateInfo, ) { if (_isEqual(storeThreadInfos[update.threadInfo.id])(update.threadInfo)) { return null; } + invariant( + update.threadInfo.minimallyEncoded, + 'update threadInfo must be minimallyEncoded', + ); return [ { type: 'replace', diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -246,10 +246,14 @@ +pinnedCount: number, }; -export type ThreadStore = { +export type LegacyThreadStore = { +threadInfos: RawThreadInfos, }; +export type ThreadStore = { + +threadInfos: MinimallyEncodedRawThreadInfos, +}; + export type ClientDBThreadInfo = { +id: string, +type: number, diff --git a/web/types/redux-types.js b/web/types/redux-types.js --- a/web/types/redux-types.js +++ b/web/types/redux-types.js @@ -3,7 +3,7 @@ import type { EntryStore, CalendarQuery } from 'lib/types/entry-types.js'; import type { InviteLinksStore } from 'lib/types/link-types.js'; import type { MessageStore } from 'lib/types/message-types.js'; -import type { ThreadStore } from 'lib/types/thread-types.js'; +import type { LegacyThreadStore, ThreadStore } from 'lib/types/thread-types.js'; import type { CurrentUserInfo, UserInfos } from 'lib/types/user-types.js'; import type { URLInfo } from 'lib/utils/url-utils.js'; @@ -13,7 +13,7 @@ +navInfo: NavInfo, +currentUserInfo: CurrentUserInfo, +entryStore: EntryStore, - +threadStore: ThreadStore, + +threadStore: LegacyThreadStore, +userInfos: UserInfos, +messageStore: MessageStore, +pushApiPublicKey: ?string,