diff --git a/keyserver/src/fetchers/thread-fetchers.js b/keyserver/src/fetchers/thread-fetchers.js --- a/keyserver/src/fetchers/thread-fetchers.js +++ b/keyserver/src/fetchers/thread-fetchers.js @@ -12,11 +12,12 @@ import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; import type { AvatarDBContent, ClientAvatar } from 'lib/types/avatar-types.js'; import type { RawMessageInfo, MessageInfo } from 'lib/types/message-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { threadTypes, type ThreadType } from 'lib/types/thread-types-enum.js'; import { type ServerThreadInfo, type RawThreadInfos, - type RawThreadInfo, + type LegacyRawThreadInfo, } from 'lib/types/thread-types.js'; import { ServerError } from 'lib/utils/errors.js'; @@ -282,7 +283,9 @@ { native: 301, web: 56 }, ); - const threadInfos: { [string]: RawThreadInfo } = {}; + const threadInfos: { + [string]: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + } = {}; for (const threadID in serverResult.threadInfos) { const serverThreadInfo = serverResult.threadInfos[threadID]; const threadInfo = rawThreadInfoFromServerThreadInfo( diff --git a/keyserver/src/shared/state-sync/threads-state-sync-spec.js b/keyserver/src/shared/state-sync/threads-state-sync-spec.js --- a/keyserver/src/shared/state-sync/threads-state-sync-spec.js +++ b/keyserver/src/shared/state-sync/threads-state-sync-spec.js @@ -2,10 +2,11 @@ import { rawThreadInfoValidator } from 'lib/permissions/minimally-encoded-thread-permissions-validators.js'; import { threadsStateSyncSpec as libSpec } from 'lib/shared/state-sync/threads-state-sync-spec.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { ClientThreadInconsistencyReportCreationRequest } from 'lib/types/report-types.js'; import { - type RawThreadInfo, type RawThreadInfos, + type LegacyRawThreadInfo, } from 'lib/types/thread-types.js'; import { hash, combineUnorderedHashes, values } from 'lib/utils/objects.js'; @@ -17,7 +18,7 @@ export const threadsStateSyncSpec: ServerStateSyncSpec< RawThreadInfos, RawThreadInfos, - RawThreadInfo, + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, $ReadOnlyArray, > = Object.freeze({ fetch, @@ -44,6 +45,8 @@ return combineUnorderedHashes(values(infos).map(getServerInfoHash)); } -function getServerInfoHash(info: RawThreadInfo) { +function getServerInfoHash( + info: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +) { return hash(validateOutput(null, rawThreadInfoValidator, info)); } diff --git a/lib/hooks/child-threads.js b/lib/hooks/child-threads.js --- a/lib/hooks/child-threads.js +++ b/lib/hooks/child-threads.js @@ -14,7 +14,8 @@ import { childThreadInfos } from '../selectors/thread-selectors.js'; import { threadInChatList } from '../shared/thread-utils.js'; import threadWatcher from '../shared/thread-watcher.js'; -import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; +import type { LegacyRawThreadInfo, ThreadInfo } from '../types/thread-types.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -40,7 +41,13 @@ }, [childThreads, predicate]); const filterSubchannels = React.useCallback( - (thread: ?(RawThreadInfo | ThreadInfo)) => { + ( + thread: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), + ) => { const candidateThreadID = thread?.id; if (!candidateThreadID) { return false; diff --git a/lib/hooks/search-threads.js b/lib/hooks/search-threads.js --- a/lib/hooks/search-threads.js +++ b/lib/hooks/search-threads.js @@ -10,10 +10,11 @@ import { sidebarInfoSelector } from '../selectors/thread-selectors.js'; import { threadIsChannel } from '../shared/thread-utils.js'; import type { SetState } from '../types/hook-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { SidebarInfo, - RawThreadInfo, ThreadInfo, + LegacyRawThreadInfo, } from '../types/thread-types.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -103,8 +104,13 @@ threadInfo: ThreadInfo, ): SearchThreadsResult { const filterFunc = React.useCallback( - (thread: ?(ThreadInfo | RawThreadInfo)) => - threadIsChannel(thread) && thread?.parentThreadID === threadInfo.id, + ( + thread: ?( + | ThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + ), + ) => threadIsChannel(thread) && thread?.parentThreadID === threadInfo.id, [threadInfo.id], ); const childThreadInfos = useFilteredChatListData(filterFunc); diff --git a/lib/permissions/minimally-encoded-thread-permissions-validators.js b/lib/permissions/minimally-encoded-thread-permissions-validators.js --- a/lib/permissions/minimally-encoded-thread-permissions-validators.js +++ b/lib/permissions/minimally-encoded-thread-permissions-validators.js @@ -22,7 +22,7 @@ threadCurrentUserInfoValidator, legacyThreadInfoValidator, } from '../types/thread-types.js'; -import type { RawThreadInfo } from '../types/thread-types.js'; +import type { LegacyRawThreadInfo } from '../types/thread-types.js'; import { tBool, tID, tShape } from '../utils/validation-utils.js'; const minimallyEncodedRoleInfoValidator: TInterface = @@ -77,7 +77,9 @@ currentUser: minimallyEncodedThreadCurrentUserInfoValidator, }); -export const rawThreadInfoValidator: TUnion = t.union([ +export const rawThreadInfoValidator: TUnion< + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +> = t.union([ legacyRawThreadInfoValidator, minimallyEncodedRawThreadInfoValidator, ]); diff --git a/lib/reducers/integrity-reducer.js b/lib/reducers/integrity-reducer.js --- a/lib/reducers/integrity-reducer.js +++ b/lib/reducers/integrity-reducer.js @@ -10,15 +10,18 @@ } from '../actions/user-actions.js'; import type { ThreadStoreOperation } from '../ops/thread-store-ops'; import type { IntegrityStore } from '../types/integrity-types'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { BaseAction } from '../types/redux-types.js'; import { fullStateSyncActionType } from '../types/socket-types.js'; -import type { RawThreadInfo } from '../types/thread-types.js'; +import type { LegacyRawThreadInfo } from '../types/thread-types.js'; import { hash } from '../utils/objects.js'; function reduceIntegrityStore( state: IntegrityStore, action: BaseAction, - threadInfos: { +[string]: RawThreadInfo }, + threadInfos: { + +[string]: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + }, threadStoreOperations: $ReadOnlyArray, ): IntegrityStore { if ( diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -88,6 +88,7 @@ } from '../types/message-types.js'; import type { RawImagesMessageInfo } from '../types/messages/images.js'; import type { RawMediaMessageInfo } from '../types/messages/media.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { type BaseAction } from '../types/redux-types.js'; import { processServerRequestsActionType } from '../types/request-types.js'; import { @@ -95,7 +96,10 @@ incrementalStateSyncActionType, } from '../types/socket-types.js'; import { threadPermissions } from '../types/thread-permission-types.js'; -import type { RawThreadInfo, RawThreadInfos } from '../types/thread-types.js'; +import type { + LegacyRawThreadInfo, + RawThreadInfos, +} from '../types/thread-types.js'; import { type ClientUpdateInfo, processUpdatesActionType, @@ -122,7 +126,7 @@ function isThreadWatched( threadID: string, - threadInfo: ?RawThreadInfo, + threadInfo: ?LegacyRawThreadInfo | ?MinimallyEncodedRawThreadInfo, watchedIDs: $ReadOnlyArray, ) { return ( diff --git a/lib/selectors/chat-selectors.js b/lib/selectors/chat-selectors.js --- a/lib/selectors/chat-selectors.js +++ b/lib/selectors/chat-selectors.js @@ -35,14 +35,15 @@ type LocalMessageInfo, isComposableMessageType, } from '../types/message-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { BaseAppState } from '../types/redux-types.js'; import { threadTypes } from '../types/thread-types-enum.js'; import { - type RawThreadInfo, type SidebarInfo, type ThreadInfo, maxReadSidebars, maxUnreadSidebars, + type LegacyRawThreadInfo, } from '../types/thread-types.js'; import type { UserInfo, @@ -227,7 +228,13 @@ } function useFilteredChatListData( - filterFunction: (threadInfo: ?(ThreadInfo | RawThreadInfo)) => boolean, + filterFunction: ( + threadInfo: ?( + | ThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + ), + ) => boolean, ): $ReadOnlyArray { const threadInfos = useSelector(threadInfoSelector); const messageInfos = useSelector(messageInfoSelector); @@ -252,7 +259,13 @@ messageStore: MessageStore, messageInfos: { +[id: string]: ?MessageInfo }, sidebarInfos: { +[id: string]: $ReadOnlyArray }, - filterFunction: (threadInfo: ?(ThreadInfo | RawThreadInfo)) => boolean, + filterFunction: ( + threadInfo: ?( + | ThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + ), + ) => boolean, ): $ReadOnlyArray { return _flow( _filter(filterFunction), diff --git a/lib/selectors/nav-selectors.js b/lib/selectors/nav-selectors.js --- a/lib/selectors/nav-selectors.js +++ b/lib/selectors/nav-selectors.js @@ -12,12 +12,13 @@ defaultCalendarQuery, } from '../types/entry-types.js'; import type { CalendarFilter } from '../types/filter-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { BaseNavInfo } from '../types/nav-types.js'; import type { BaseAppState } from '../types/redux-types.js'; import type { RelativeMemberInfo, - RawThreadInfo, ThreadInfo, + LegacyRawThreadInfo, } from '../types/thread-types'; import type { UserInfo } from '../types/user-types.js'; import { getConfig } from '../utils/config.js'; @@ -120,7 +121,9 @@ } function useThreadSearchIndex( - threadInfos: $ReadOnlyArray, + threadInfos: $ReadOnlyArray< + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, + >, ): SearchIndex { const userInfos = useSelector(state => state.userStore.userInfos); const viewerID = useSelector( diff --git a/lib/selectors/thread-selectors.js b/lib/selectors/thread-selectors.js --- a/lib/selectors/thread-selectors.js +++ b/lib/selectors/thread-selectors.js @@ -39,6 +39,7 @@ import type { ClientAvatar, ClientEmojiAvatar } from '../types/avatar-types'; import type { EntryInfo } from '../types/entry-types.js'; import type { MessageStore, RawMessageInfo } from '../types/message-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { BaseAppState } from '../types/redux-types.js'; import { threadPermissions } from '../types/thread-permission-types.js'; import { @@ -50,8 +51,8 @@ SidebarInfo, RelativeMemberInfo, ThreadInfo, - RawThreadInfo, RawThreadInfos, + LegacyRawThreadInfo, } from '../types/thread-types.js'; import { dateString, dateFromString } from '../utils/date-utils.js'; import { values } from '../utils/objects.js'; @@ -343,7 +344,7 @@ (state: BaseAppState<>) => state.threadStore.threadInfos[threadID], relativeMemberInfoSelectorForMembersOfThread(threadID), ( - threadInfo: ?RawThreadInfo, + threadInfo: ?LegacyRawThreadInfo | ?MinimallyEncodedRawThreadInfo, members: $ReadOnlyArray, ): boolean => { if (!threadInfo) { diff --git a/lib/shared/avatar-utils.js b/lib/shared/avatar-utils.js --- a/lib/shared/avatar-utils.js +++ b/lib/shared/avatar-utils.js @@ -16,8 +16,9 @@ ResolvedClientAvatar, GenericUserInfoWithAvatar, } from '../types/avatar-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { threadTypes } from '../types/thread-types-enum.js'; -import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { LegacyRawThreadInfo, ThreadInfo } from '../types/thread-types.js'; import type { UserInfos } from '../types/user-types.js'; import { useSelector } from '../utils/redux-utils.js'; import { ashoatKeyserverID } from '../utils/validation-utils.js'; @@ -270,7 +271,7 @@ } function getUserAvatarForThread( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, viewerID: ?string, userInfos: UserInfos, ): ClientAvatar { @@ -296,7 +297,7 @@ } function getAvatarForThread( - thread: RawThreadInfo | ThreadInfo, + thread: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, containingThreadInfo: ?ThreadInfo, ): ClientAvatar { if (thread.avatar) { @@ -312,7 +313,9 @@ return getDefaultAvatar(thread.id, thread.color); } -function useAvatarForThread(thread: RawThreadInfo | ThreadInfo): ClientAvatar { +function useAvatarForThread( + thread: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +): ClientAvatar { const containingThreadID = thread.containingThreadID; const containingThreadInfo = useSelector(state => containingThreadID ? threadInfoSelector(state)[containingThreadID] : null, diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -42,7 +42,8 @@ RawReactionMessageInfo, ReactionMessageInfo, } from '../types/messages/reaction.js'; -import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; +import type { LegacyRawThreadInfo, ThreadInfo } from '../types/thread-types.js'; import type { UserInfos } from '../types/user-types.js'; import { type EntityText, @@ -680,7 +681,7 @@ function isInvalidPinSourceForThread( messageInfo: RawMessageInfo | MessageInfo, - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ): boolean { const isValidPinSource = !isInvalidPinSource(messageInfo); const isFirstMessageInSidebar = threadInfo.sourceMessageID === messageInfo.id; diff --git a/lib/shared/state-sync/threads-state-sync-spec.js b/lib/shared/state-sync/threads-state-sync-spec.js --- a/lib/shared/state-sync/threads-state-sync-spec.js +++ b/lib/shared/state-sync/threads-state-sync-spec.js @@ -4,6 +4,7 @@ import { createSelector } from 'reselect'; import type { StateSyncSpec, BoundStateSyncSpec } from './state-sync-spec.js'; +import type { MinimallyEncodedRawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import type { AppState } from '../../types/redux-types.js'; import { reportTypes, @@ -11,8 +12,8 @@ } from '../../types/report-types.js'; import type { ProcessServerRequestAction } from '../../types/request-types.js'; import { - type RawThreadInfo, type RawThreadInfos, + type LegacyRawThreadInfo, } from '../../types/thread-types.js'; import { actionLogger } from '../../utils/action-logger.js'; import { getConfig } from '../../utils/config.js'; @@ -25,7 +26,7 @@ state: AppState, ) => BoundStateSyncSpec< RawThreadInfos, - RawThreadInfo, + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, $ReadOnlyArray, > = createSelector( (state: AppState) => state.integrityStore.threadHashes, @@ -44,7 +45,7 @@ export const threadsStateSyncSpec: StateSyncSpec< RawThreadInfos, - RawThreadInfo, + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, $ReadOnlyArray, > = Object.freeze({ hashKey: 'threadInfos', diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -96,7 +96,6 @@ ChangeThreadSettingsPayload, UserProfileThreadInfo, RelativeMemberInfo, - RawThreadInfo, ThreadInfo, RawThreadInfos, } from '../types/thread-types.js'; @@ -128,7 +127,11 @@ import { pendingThreadIDRegex } from '../utils/validation-utils.js'; function threadHasPermission( - threadInfo: ?(ThreadInfo | RawThreadInfo), + threadInfo: ?( + | ThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + ), permission: ThreadPermission, ): boolean { if (!threadInfo) { @@ -145,7 +148,13 @@ return permissionLookup(threadInfo.currentUser.permissions, permission); } -function viewerIsMember(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function viewerIsMember( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return !!( threadInfo && threadInfo.currentUser.role !== null && @@ -153,38 +162,76 @@ ); } -function threadIsInHome(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function threadIsInHome( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return !!(threadInfo && threadInfo.currentUser.subscription.home); } // Can have messages -function threadInChatList(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function threadInChatList( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return ( viewerIsMember(threadInfo) && threadHasPermission(threadInfo, threadPermissions.VISIBLE) ); } -function threadIsTopLevel(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function threadIsTopLevel( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return threadInChatList(threadInfo) && threadIsChannel(threadInfo); } -function threadIsChannel(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function threadIsChannel( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return !!(threadInfo && threadInfo.type !== threadTypes.SIDEBAR); } -function threadIsSidebar(threadInfo: ?(RawThreadInfo | ThreadInfo)): boolean { +function threadIsSidebar( + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), +): boolean { return threadInfo?.type === threadTypes.SIDEBAR; } function threadInBackgroundChatList( - threadInfo: ?(RawThreadInfo | ThreadInfo), + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), ): boolean { return threadInChatList(threadInfo) && !threadIsInHome(threadInfo); } function threadInHomeChatList( - threadInfo: ?(RawThreadInfo | ThreadInfo), + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), ): boolean { return threadInChatList(threadInfo) && threadIsInHome(threadInfo); } @@ -192,7 +239,11 @@ // Can have Calendar entries, // does appear as a top-level entity in the thread list function threadInFilterList( - threadInfo: ?(RawThreadInfo | ThreadInfo), + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), ): boolean { return ( threadInChatList(threadInfo) && @@ -202,7 +253,11 @@ } function userIsMember( - threadInfo: ?(RawThreadInfo | ThreadInfo), + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + ), userID: string, ): boolean { if (!threadInfo) { @@ -231,9 +286,9 @@ ); } -function threadMembersWithoutAddedAshoat( - threadInfo: T, -): $PropertyType { +function threadMembersWithoutAddedAshoat< + T: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +>(threadInfo: T): $PropertyType { if (threadInfo.community !== genesis.id) { return threadInfo.members; } @@ -247,7 +302,7 @@ } function threadOrParentThreadIsGroupChat( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ) { return threadMembersWithoutAddedAshoat(threadInfo).length > 2; } @@ -261,7 +316,7 @@ } function getSingleOtherUser( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, viewerID: ?string, ): ?string { if (!viewerID) { @@ -742,7 +797,7 @@ serverThreadInfo: ServerThreadInfo, viewerID: string, options?: RawThreadInfoOptions, -): ?RawThreadInfo { +): ?LegacyRawThreadInfo | ?MinimallyEncodedRawThreadInfo { const filterThreadEditAvatarPermission = options?.filterThreadEditAvatarPermission; const excludePinInfo = options?.excludePinInfo; @@ -895,7 +950,7 @@ } function threadInfoFromRawThreadInfo( - rawThreadInfo: RawThreadInfo, + rawThreadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, viewerID: ?string, userInfos: UserInfos, ): MinimallyEncodedThreadInfo { @@ -1010,7 +1065,7 @@ } function threadIsWithBlockedUserOnly( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, viewerID: ?string, userInfos: UserInfos, checkOnlyViewerBlock?: boolean, @@ -1042,7 +1097,7 @@ } function threadFrozenDueToBlock( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, viewerID: ?string, userInfos: UserInfos, ): boolean { @@ -1050,7 +1105,7 @@ } function threadFrozenDueToViewerBlock( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, viewerID: ?string, userInfos: UserInfos, ): boolean { @@ -1066,7 +1121,7 @@ function memberIsAdmin( memberInfo: RelativeMemberInfo | MemberInfo, - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ): boolean { return !!( memberInfo.role && roleIsAdminRole(threadInfo.roles[memberInfo.role]) @@ -1089,7 +1144,12 @@ } function threadHasAdminRole( - threadInfo: ?(RawThreadInfo | ThreadInfo | ServerThreadInfo), + threadInfo: ?( + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + | ServerThreadInfo + ), ): boolean { if (!threadInfo) { return false; @@ -1098,7 +1158,7 @@ } function threadOrParentThreadHasAdminRole( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ) { return ( threadMembersWithoutAddedAshoat(threadInfo).filter(member => @@ -1346,7 +1406,11 @@ } function threadMemberHasPermission( - threadInfo: ServerThreadInfo | RawThreadInfo | ThreadInfo, + threadInfo: + | ServerThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, memberID: string, permission: ThreadPermission, ): boolean { @@ -1425,7 +1489,11 @@ } function getContainingThreadID( - parentThreadInfo: ?ServerThreadInfo | RawThreadInfo | ThreadInfo, + parentThreadInfo: + | ?ServerThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, threadType: ThreadType, ): ?string { if (!parentThreadInfo) { @@ -1441,7 +1509,11 @@ } function getCommunity( - parentThreadInfo: ?ServerThreadInfo | RawThreadInfo | ThreadInfo, + parentThreadInfo: + | ?ServerThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, ): ?string { if (!parentThreadInfo) { return null; @@ -1633,7 +1705,7 @@ } function threadInfoInsideCommunity( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, communityID: string, ): boolean { return threadInfo.community === communityID || threadInfo.id === communityID; @@ -1715,14 +1787,16 @@ }, [threadInfo]); } -function communityOrThreadNoun(threadInfo: RawThreadInfo | ThreadInfo): string { +function communityOrThreadNoun( + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +): string { return threadTypeIsCommunityRoot(threadInfo.type) ? 'community' : threadNoun(threadInfo.type, threadInfo.parentThreadID); } function getThreadsToDeleteText( - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ): string { return `${ threadTypeIsCommunityRoot(threadInfo.type) diff --git a/lib/shared/user-utils.js b/lib/shared/user-utils.js --- a/lib/shared/user-utils.js +++ b/lib/shared/user-utils.js @@ -2,8 +2,9 @@ import { memberHasAdminPowers } from './thread-utils.js'; import { useENSNames } from '../hooks/ens-cache.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { - RawThreadInfo, + LegacyRawThreadInfo, ServerThreadInfo, ThreadInfo, } from '../types/thread-types.js'; @@ -33,7 +34,11 @@ } function useKeyserverAdmin( - community: ThreadInfo | RawThreadInfo | ServerThreadInfo, + community: + | ThreadInfo + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ServerThreadInfo, ): ?UserInfo { const userInfos = useSelector(state => state.userStore.userInfos); // This hack only works as long as there is only one admin diff --git a/lib/types/request-types.js b/lib/types/request-types.js --- a/lib/types/request-types.js +++ b/lib/types/request-types.js @@ -19,7 +19,7 @@ ClientThreadInconsistencyReportShape, ClientEntryInconsistencyReportShape, } from './report-types.js'; -import { type RawThreadInfo } from './thread-types.js'; +import type { LegacyRawThreadInfo } from './thread-types.js'; import { type CurrentUserInfo, currentUserInfoValidator, @@ -104,7 +104,7 @@ }>; type StateChanges = Partial<{ - +rawThreadInfos: RawThreadInfo[], + +rawThreadInfos: LegacyRawThreadInfo[] | MinimallyEncodedRawThreadInfo[], +rawEntryInfos: RawEntryInfo[], +currentUserInfo: CurrentUserInfo, +userInfos: AccountUserInfo[], 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 @@ -451,14 +451,14 @@ export type RoleModificationRequest = CreateRoleAction | EditRoleAction; export type RoleModificationResult = { - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type RoleModificationPayload = { - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, @@ -470,14 +470,14 @@ }; export type RoleDeletionResult = { - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, }; export type RoleDeletionPayload = { - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +updatesResult: { +newUpdates: $ReadOnlyArray, }, diff --git a/lib/types/update-types.js b/lib/types/update-types.js --- a/lib/types/update-types.js +++ b/lib/types/update-types.js @@ -7,7 +7,8 @@ type RawMessageInfo, type MessageTruncationStatus, } from './message-types.js'; -import type { RawThreadInfo } from './thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from './minimally-encoded-thread-permissions-types.js'; +import type { LegacyRawThreadInfo } from './thread-types.js'; import { type UserInfo, userInfoValidator, @@ -183,7 +184,7 @@ +type: 1, +id: string, +time: number, - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, }; export type ThreadReadStatusUpdateInfo = { @@ -205,7 +206,7 @@ +type: 4, +id: string, +time: number, - +threadInfo: RawThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, +rawMessageInfos: $ReadOnlyArray, +truncationStatus: MessageTruncationStatus, +rawEntryInfos: $ReadOnlyArray, diff --git a/lib/utils/drawer-utils.react.js b/lib/utils/drawer-utils.react.js --- a/lib/utils/drawer-utils.react.js +++ b/lib/utils/drawer-utils.react.js @@ -4,9 +4,10 @@ import { values } from './objects.js'; import { threadInFilterList, threadIsChannel } from '../shared/thread-utils.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { communitySubthreads } from '../types/thread-types-enum.js'; import type { - RawThreadInfo, + LegacyRawThreadInfo, ResolvedThreadInfo, ThreadInfo, } from '../types/thread-types.js'; @@ -104,7 +105,10 @@ function filterThreadIDsBelongingToCommunity( communityID: string, threadInfosObj: { - +[id: string]: RawThreadInfo | ThreadInfo, + +[id: string]: + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, }, ): $ReadOnlySet { const threadInfos = values(threadInfosObj); diff --git a/lib/utils/entity-text.js b/lib/utils/entity-text.js --- a/lib/utils/entity-text.js +++ b/lib/utils/entity-text.js @@ -9,12 +9,13 @@ import { useENSNames, type UseENSNamesOptions } from '../hooks/ens-cache.js'; import { threadNoun } from '../shared/thread-utils.js'; import { stringForUser } from '../shared/user-utils.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { type ThreadType, threadTypes, threadTypeValidator, } from '../types/thread-types-enum.js'; -import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { LegacyRawThreadInfo, ThreadInfo } from '../types/thread-types.js'; import { basePluralize } from '../utils/text-utils.js'; export type UserEntity = { @@ -138,13 +139,19 @@ } | { +display?: 'shortName', - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, +subchannel?: ?boolean, +possessive?: ?boolean, } | { +display: 'alwaysDisplayShortName', - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo, +possessive?: ?boolean, } | { diff --git a/lib/utils/message-pinning-utils.js b/lib/utils/message-pinning-utils.js --- a/lib/utils/message-pinning-utils.js +++ b/lib/utils/message-pinning-utils.js @@ -3,12 +3,13 @@ import { isInvalidPinSourceForThread } from '../shared/message-utils.js'; import { threadHasPermission } from '../shared/thread-utils.js'; import type { RawMessageInfo, MessageInfo } from '../types/message-types.js'; +import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { threadPermissions } from '../types/thread-permission-types.js'; -import type { RawThreadInfo, ThreadInfo } from '../types/thread-types.js'; +import type { LegacyRawThreadInfo, ThreadInfo } from '../types/thread-types.js'; function canToggleMessagePin( messageInfo: RawMessageInfo | MessageInfo, - threadInfo: RawThreadInfo | ThreadInfo, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, ): boolean { const isValidMessage = !isInvalidPinSourceForThread(messageInfo, threadInfo); const hasManagePinsPermission = threadHasPermission( diff --git a/lib/utils/thread-ops-utils.js b/lib/utils/thread-ops-utils.js --- a/lib/utils/thread-ops-utils.js +++ b/lib/utils/thread-ops-utils.js @@ -24,12 +24,11 @@ legacyMemberInfoValidator, type LegacyRawThreadInfo, legacyRoleInfoValidator, - type RawThreadInfo, threadCurrentUserInfoValidator, } from '../types/thread-types.js'; function convertRawThreadInfoToClientDBThreadInfo( - rawThreadInfo: RawThreadInfo, + rawThreadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, ): ClientDBThreadInfo { const { minimallyEncoded, ...rest } = rawThreadInfo; return { diff --git a/native/avatars/edit-thread-avatar.react.js b/native/avatars/edit-thread-avatar.react.js --- a/native/avatars/edit-thread-avatar.react.js +++ b/native/avatars/edit-thread-avatar.react.js @@ -6,7 +6,11 @@ import { ActivityIndicator, TouchableOpacity, View } from 'react-native'; import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import { useNativeSetThreadAvatar, @@ -22,7 +26,7 @@ import { useStyles } from '../themes/colors.js'; type Props = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +disabled?: boolean, }; function EditThreadAvatar(props: Props): React.Node { diff --git a/native/avatars/thread-avatar.react.js b/native/avatars/thread-avatar.react.js --- a/native/avatars/thread-avatar.react.js +++ b/native/avatars/thread-avatar.react.js @@ -8,9 +8,10 @@ } from 'lib/shared/avatar-utils.js'; import { getSingleOtherUser } from 'lib/shared/thread-utils.js'; import type { AvatarSize } from 'lib/types/avatar-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import type { - RawThreadInfo, + LegacyRawThreadInfo, ResolvedThreadInfo, ThreadInfo, } from 'lib/types/thread-types.js'; @@ -19,7 +20,11 @@ import { useSelector } from '../redux/redux-utils.js'; type Props = { - +threadInfo: RawThreadInfo | ThreadInfo | ResolvedThreadInfo, + +threadInfo: + | LegacyRawThreadInfo + | MinimallyEncodedRawThreadInfo + | ThreadInfo + | ResolvedThreadInfo, +size: AvatarSize, }; diff --git a/native/chat/settings/emoji-thread-avatar-creation.react.js b/native/chat/settings/emoji-thread-avatar-creation.react.js --- a/native/chat/settings/emoji-thread-avatar-creation.react.js +++ b/native/chat/settings/emoji-thread-avatar-creation.react.js @@ -6,7 +6,11 @@ import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js'; import type { UpdateUserAvatarRequest } from 'lib/types/avatar-types.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import { useNativeSetThreadAvatar } from '../../avatars/avatar-hooks.js'; import EmojiAvatarCreation from '../../avatars/emoji-avatar-creation.react.js'; @@ -16,7 +20,7 @@ import { useSelector } from '../../redux/redux-utils.js'; export type EmojiThreadAvatarCreationParams = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, }; type Props = { diff --git a/native/redux/client-db-utils.js b/native/redux/client-db-utils.js --- a/native/redux/client-db-utils.js +++ b/native/redux/client-db-utils.js @@ -7,9 +7,10 @@ ClientDBMessageInfo, ClientDBThreadMessageInfo, } from 'lib/types/message-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { ClientDBThreadInfo, - RawThreadInfo, + LegacyRawThreadInfo, RawThreadInfos, } from 'lib/types/thread-types.js'; import { @@ -71,7 +72,10 @@ // Convert `rawThreadInfo`s to a map of `threadID` => `threadInfo`. const threadIDToThreadInfo = rawThreadInfos.reduce( - (acc: { [string]: RawThreadInfo }, threadInfo: RawThreadInfo) => { + ( + acc: { [string]: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo }, + threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + ) => { acc[threadInfo.id] = threadInfo; return acc; }, @@ -82,9 +86,9 @@ const updatedThreadIDToThreadInfo = migrationFunc(threadIDToThreadInfo); // Convert the updated `threadInfo`s back into an array. - const updatedRawThreadInfos: $ReadOnlyArray = values( - updatedThreadIDToThreadInfo, - ); + const updatedRawThreadInfos: $ReadOnlyArray< + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + > = values(updatedThreadIDToThreadInfo); // Translate `RawThreadInfo`s to `ClientDBThreadInfo`s. const convertedClientDBThreadInfos: $ReadOnlyArray = diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -63,6 +63,7 @@ type RawMessageInfo, } from 'lib/types/message-types.js'; import { minimallyEncodeRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { ReportStore, ClientReportCreationRequest, @@ -75,7 +76,6 @@ import type { ClientDBThreadInfo, LegacyRawThreadInfo, - RawThreadInfo, RawThreadInfos, } from 'lib/types/thread-types.js'; import { @@ -383,7 +383,9 @@ return state; } - const threadInfos: { [string]: RawThreadInfo } = {}; + const threadInfos: { + [string]: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + } = {}; const stack = [...rootIDs]; while (stack.length > 0) { const threadID = stack.shift(); @@ -995,7 +997,12 @@ threadStoreInfos: RawThreadInfos, ): RawThreadInfos => Object.keys(threadStoreInfos).reduce( - (acc: { [string]: RawThreadInfo }, key: string) => { + ( + acc: { + [string]: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + }, + key: string, + ) => { const threadInfo = threadStoreInfos[key]; acc[threadInfo.id] = threadInfo.minimallyEncoded ? threadInfo diff --git a/web/avatars/edit-thread-avatar-menu.react.js b/web/avatars/edit-thread-avatar-menu.react.js --- a/web/avatars/edit-thread-avatar-menu.react.js +++ b/web/avatars/edit-thread-avatar-menu.react.js @@ -6,7 +6,11 @@ import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import { useUploadAvatarMedia } from './avatar-hooks.react.js'; import css from './edit-avatar-menu.css'; @@ -22,7 +26,7 @@ ); type Props = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, }; function EditThreadAvatarMenu(props: Props): React.Node { const { threadInfo } = props; diff --git a/web/avatars/edit-thread-avatar.react.js b/web/avatars/edit-thread-avatar.react.js --- a/web/avatars/edit-thread-avatar.react.js +++ b/web/avatars/edit-thread-avatar.react.js @@ -5,15 +5,19 @@ import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; import { threadHasPermission } from 'lib/shared/thread-utils.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { threadPermissions } from 'lib/types/thread-permission-types.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import EditThreadAvatarMenu from './edit-thread-avatar-menu.react.js'; import css from './edit-thread-avatar.css'; import ThreadAvatar from './thread-avatar.react.js'; type Props = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +disabled?: boolean, }; function EditThreadAvatar(props: Props): React.Node { diff --git a/web/avatars/thread-avatar.react.js b/web/avatars/thread-avatar.react.js --- a/web/avatars/thread-avatar.react.js +++ b/web/avatars/thread-avatar.react.js @@ -8,14 +8,18 @@ } from 'lib/shared/avatar-utils.js'; import { getSingleOtherUser } from 'lib/shared/thread-utils.js'; import type { AvatarSize } from 'lib/types/avatar-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import Avatar from './avatar.react.js'; import { useSelector } from '../redux/redux-utils.js'; type Props = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, +size: AvatarSize, +showSpinner?: boolean, }; diff --git a/web/avatars/thread-emoji-avatar-selection-modal.react.js b/web/avatars/thread-emoji-avatar-selection-modal.react.js --- a/web/avatars/thread-emoji-avatar-selection-modal.react.js +++ b/web/avatars/thread-emoji-avatar-selection-modal.react.js @@ -12,12 +12,16 @@ ClientAvatar, ClientEmojiAvatar, } from 'lib/types/avatar-types.js'; -import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { + LegacyRawThreadInfo, + ThreadInfo, +} from 'lib/types/thread-types.js'; import EmojiAvatarSelectionModal from './emoji-avatar-selection-modal.react.js'; type Props = { - +threadInfo: RawThreadInfo | ThreadInfo, + +threadInfo: LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo | ThreadInfo, }; function ThreadEmojiAvatarSelectionModal(props: Props): React.Node { diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js --- a/web/redux/initial-state-gate.js +++ b/web/redux/initial-state-gate.js @@ -8,7 +8,8 @@ import type { ThreadStoreOperation } from 'lib/ops/thread-store-ops.js'; import { allUpdatesCurrentAsOfSelector } from 'lib/selectors/keyserver-selectors.js'; import { canUseDatabaseOnWeb } from 'lib/shared/web-database.js'; -import type { RawThreadInfo } from 'lib/types/thread-types.js'; +import type { MinimallyEncodedRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { LegacyRawThreadInfo } from 'lib/types/thread-types.js'; import { convertIDToNewSchema } from 'lib/utils/migration-utils.js'; import { entries } from 'lib/utils/objects.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; @@ -97,13 +98,18 @@ const threadStoreOperations: ThreadStoreOperation[] = entries( threadInfos, - ).map(([id, threadInfo]: [string, RawThreadInfo]) => ({ - type: 'replace', - payload: { - id, - threadInfo, - }, - })); + ).map( + ([id, threadInfo]: [ + string, + LegacyRawThreadInfo | MinimallyEncodedRawThreadInfo, + ]) => ({ + type: 'replace', + payload: { + id, + threadInfo, + }, + }), + ); await processDBStoreOperations( {