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 @@ -60,8 +60,10 @@ import type { MinimallyEncodedMemberInfo, MinimallyEncodedRawThreadInfo, + MinimallyEncodedRelativeMemberInfo, MinimallyEncodedRoleInfo, MinimallyEncodedThreadCurrentUserInfo, + MinimallyEncodedThreadInfo, } from '../types/minimally-encoded-thread-permissions-types.js'; import { userRelationshipStatus } from '../types/relationship-types.js'; import { @@ -119,7 +121,12 @@ import { pendingThreadIDRegex } from '../utils/validation-utils.js'; function threadHasPermission( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), permission: ThreadPermission, ): boolean { if (!threadInfo) { @@ -137,7 +144,12 @@ } function viewerIsMember( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return !!( threadInfo && @@ -147,14 +159,24 @@ } function threadIsInHome( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return !!(threadInfo && threadInfo.currentUser.subscription.home); } // Can have messages function threadInChatList( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return ( viewerIsMember(threadInfo) && @@ -163,31 +185,56 @@ } function threadIsTopLevel( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return threadInChatList(threadInfo) && threadIsChannel(threadInfo); } function threadIsChannel( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return !!(threadInfo && threadInfo.type !== threadTypes.SIDEBAR); } function threadIsSidebar( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return threadInfo?.type === threadTypes.SIDEBAR; } function threadInBackgroundChatList( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return threadInChatList(threadInfo) && !threadIsInHome(threadInfo); } function threadInHomeChatList( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return threadInChatList(threadInfo) && threadIsInHome(threadInfo); } @@ -195,7 +242,12 @@ // Can have Calendar entries, // does appear as a top-level entity in the thread list function threadInFilterList( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), ): boolean { return ( threadInChatList(threadInfo) && @@ -205,7 +257,12 @@ } function userIsMember( - threadInfo: ?(ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo), + threadInfo: ?( + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo + ), userID: string, ): boolean { if (!threadInfo) { @@ -219,7 +276,10 @@ function threadActualMembers( memberInfos: $ReadOnlyArray< - MemberInfo | RelativeMemberInfo | MinimallyEncodedMemberInfo, + | MemberInfo + | RelativeMemberInfo + | MinimallyEncodedMemberInfo + | MinimallyEncodedRelativeMemberInfo, >, ): $ReadOnlyArray { return memberInfos @@ -228,7 +288,11 @@ } function threadOtherMembers< - T: MemberInfo | RelativeMemberInfo | MinimallyEncodedMemberInfo, + T: + | MemberInfo + | RelativeMemberInfo + | MinimallyEncodedMemberInfo + | MinimallyEncodedRelativeMemberInfo, >(memberInfos: $ReadOnlyArray, viewerID: ?string): $ReadOnlyArray { return memberInfos.filter( memberInfo => memberInfo.role && memberInfo.id !== viewerID, @@ -236,7 +300,11 @@ } function threadMembersWithoutAddedAshoat< - T: ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo, + T: + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, >(threadInfo: T): $PropertyType { if (threadInfo.community !== genesis.id) { return threadInfo.members; @@ -246,12 +314,18 @@ ); } -function threadIsGroupChat(threadInfo: ThreadInfo): boolean { +function threadIsGroupChat( + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, +): boolean { return threadInfo.members.length > 2; } function threadOrParentThreadIsGroupChat( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ) { return threadMembersWithoutAddedAshoat(threadInfo).length > 2; } @@ -265,7 +339,11 @@ } function getSingleOtherUser( - threadInfo: ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, viewerID: ?string, ): ?string { if (!viewerID) { @@ -456,7 +534,9 @@ // Returns map from lowercase username to AccountUserInfo function memberLowercaseUsernameMap( - members: $ReadOnlyArray, + members: $ReadOnlyArray< + RelativeMemberInfo | MinimallyEncodedRelativeMemberInfo, + >, ): Map { const memberMap = new Map(); for (const member of members) { @@ -472,7 +552,7 @@ // Returns map from user ID to AccountUserInfo function extractMentionedMembers( text: string, - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, ): Map { const memberMap = memberLowercaseUsernameMap(threadInfo.members); const mentions = extractUserMentionsFromText(text); @@ -491,8 +571,8 @@ // they will be automatically added to that sidebar function extractNewMentionedParentMembers( messageText: string, - threadInfo: ThreadInfo, - parentThreadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, + parentThreadInfo: ThreadInfo | MinimallyEncodedThreadInfo, ): AccountUserInfo[] { const mentionedMembersOfParent = extractMentionedMembers( messageText, @@ -946,7 +1026,7 @@ } function getMinimallyEncodedCurrentUser( - threadInfo: MinimallyEncodedRawThreadInfo, + threadInfo: MinimallyEncodedRawThreadInfo | MinimallyEncodedThreadInfo, viewerID: ?string, userInfos: UserInfos, ): MinimallyEncodedThreadCurrentUserInfo { @@ -968,7 +1048,11 @@ } function threadIsWithBlockedUserOnly( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, viewerID: ?string, userInfos: UserInfos, checkOnlyViewerBlock?: boolean, @@ -1000,7 +1084,11 @@ } function threadFrozenDueToBlock( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, viewerID: ?string, userInfos: UserInfos, ): boolean { @@ -1008,7 +1096,11 @@ } function threadFrozenDueToViewerBlock( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, viewerID: ?string, userInfos: UserInfos, ): boolean { @@ -1023,8 +1115,16 @@ }; function memberIsAdmin( - memberInfo: RelativeMemberInfo | MemberInfo | MinimallyEncodedMemberInfo, - threadInfo: ThreadInfo | RawThreadInfo | MinimallyEncodedRawThreadInfo, + memberInfo: + | RelativeMemberInfo + | MemberInfo + | MinimallyEncodedMemberInfo + | MinimallyEncodedRelativeMemberInfo, + threadInfo: + | ThreadInfo + | RawThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ): boolean { return !!( memberInfo.role && roleIsAdminRole(threadInfo.roles[memberInfo.role]) @@ -1038,7 +1138,8 @@ | RelativeMemberInfo | MemberInfo | ServerMemberInfo - | MinimallyEncodedMemberInfo, + | MinimallyEncodedMemberInfo + | MinimallyEncodedRelativeMemberInfo, ): boolean { if (memberInfo.minimallyEncoded) { return hasPermission(memberInfo.permissions, threadPermissions.CHANGE_ROLE); @@ -1058,6 +1159,7 @@ | ThreadInfo | ServerThreadInfo | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo ), ): boolean { if (!threadInfo) { @@ -1067,7 +1169,11 @@ } function threadOrParentThreadHasAdminRole( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ) { return ( threadMembersWithoutAddedAshoat(threadInfo).filter(member => @@ -1306,7 +1412,8 @@ | ServerThreadInfo | RawThreadInfo | ThreadInfo - | MinimallyEncodedRawThreadInfo, + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, memberID: string, permission: ThreadPermission, ): boolean { @@ -1323,7 +1430,7 @@ } function useCanCreateSidebarFromMessage( - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, messageInfo: ComposableMessageInfo | RobotextMessageInfo, ): boolean { const messageCreatorUserInfo = useSelector( @@ -1352,7 +1459,7 @@ } function useSidebarExistsOrCanBeCreated( - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, messageItem: ChatMessageInfoItem, ): boolean { const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage( @@ -1385,7 +1492,8 @@ | ?ServerThreadInfo | RawThreadInfo | ThreadInfo - | MinimallyEncodedRawThreadInfo, + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, threadType: ThreadType, ): ?string { if (!parentThreadInfo) { @@ -1405,7 +1513,8 @@ | ?ServerThreadInfo | RawThreadInfo | ThreadInfo - | MinimallyEncodedRawThreadInfo, + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ): ?string { if (!parentThreadInfo) { return null; @@ -1504,7 +1613,7 @@ } function removeMemberFromThread( - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, memberInfo: RelativeMemberInfo, dispatchActionPromise: DispatchActionPromise, removeUserFromThreadServerCall: ( @@ -1523,7 +1632,7 @@ } function switchMemberAdminRoleInThread( - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, memberInfo: RelativeMemberInfo, isCurrentlyAdmin: boolean, dispatchActionPromise: DispatchActionPromise, @@ -1555,8 +1664,8 @@ } function getAvailableThreadMemberActions( - memberInfo: RelativeMemberInfo, - threadInfo: ThreadInfo, + memberInfo: RelativeMemberInfo | MinimallyEncodedRelativeMemberInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, canEdit: ?boolean = true, ): $ReadOnlyArray<'change_role' | 'remove_user'> { const role = memberInfo.role; @@ -1620,7 +1729,11 @@ } function threadInfoInsideCommunity( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, communityID: string, ): boolean { return threadInfo.community === communityID || threadInfo.id === communityID; @@ -1631,7 +1744,7 @@ }; function useRoleMemberCountsForCommunity( - threadInfo: ThreadInfo, + threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, ): RoleAndMemberCount { return React.useMemo(() => { const roleIDsToNames = {}; @@ -1697,7 +1810,11 @@ } function communityOrThreadNoun( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ): string { return threadTypeIsCommunityRoot(threadInfo.type) ? 'community' @@ -1705,7 +1822,11 @@ } function getThreadsToDeleteText( - threadInfo: RawThreadInfo | ThreadInfo | MinimallyEncodedRawThreadInfo, + threadInfo: + | RawThreadInfo + | ThreadInfo + | MinimallyEncodedRawThreadInfo + | MinimallyEncodedThreadInfo, ): string { return `${ threadTypeIsCommunityRoot(threadInfo.type) 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 @@ -48,11 +48,11 @@ isSender: t.Boolean, }); -export type RelativeMemberInfo = { +export type RelativeMemberInfo = $ReadOnly<{ ...MemberInfo, +username: ?string, +isViewer: boolean, -}; +}>; const relativeMemberInfoValidator = tShape({ ...memberInfoValidator.meta.props, username: t.maybe(t.String),