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 @@ -13,8 +13,10 @@ import { relationshipBlockedInEitherDirection } from './relationship-utils.js'; import type { SidebarItem } from './sidebar-item-utils.js'; import { dmThreadProtocol } from './threads/protocols/dm-thread-protocol.js'; +import { farcasterThreadProtocol } from './threads/protocols/farcaster-thread-protocol.js'; import { keyserverThreadProtocol } from './threads/protocols/keyserver-thread-protocol.js'; import { protocols } from './threads/protocols/thread-protocols.js'; +import type { ThreadProtocol } from './threads/thread-spec.js'; import { threadSpecs, threadTypeIsCommunityRoot, @@ -113,6 +115,7 @@ import { entries, values } from '../utils/objects.js'; import { useSelector } from '../utils/redux-utils.js'; import { userSurfacedPermissionsFromRolePermissions } from '../utils/role-utils.js'; +import { supportsFarcasterDCs } from '../utils/services-utils.js'; import { firstLine } from '../utils/string-utils.js'; import { pendingThreadIDRegex, @@ -1119,6 +1122,7 @@ +searching: boolean, +userInfoInputArray: $ReadOnlyArray, +allUsersSupportThickThreads: boolean, + +allUsersSupportFarcasterThreads: boolean, }; type ExistingThreadInfoFinder = ( params: ExistingThreadInfoFinderParams, @@ -1182,9 +1186,13 @@ return baseThreadInfo; } - const protocol = params.allUsersSupportThickThreads - ? dmThreadProtocol - : keyserverThreadProtocol; + let protocol: ThreadProtocol = keyserverThreadProtocol; + if (params.allUsersSupportFarcasterThreads && supportsFarcasterDCs) { + protocol = farcasterThreadProtocol; + } else if (params.allUsersSupportThickThreads) { + protocol = dmThreadProtocol; + } + return createPendingThread({ viewerID, threadType: protocol.pendingThreadType(userInfoInputArray.length), diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -8,6 +8,7 @@ import genesis from 'lib/facts/genesis.js'; import { + useUsersSupportFarcasterDCs, useUsersSupportingProtocols, useUsersSupportThickThreads, } from 'lib/hooks/user-identities-hooks.js'; @@ -287,7 +288,8 @@ useExistingThreadInfoFinder(baseThreadInfo); const checkUsersThickThreadSupport = useUsersSupportThickThreads(); - const { allUsersSupportThickThreads } = + const checkUsersFarcasterDCsSupport = useUsersSupportFarcasterDCs(); + const { allUsersSupportThickThreads, allUsersSupportFarcasterThreads } = useUsersSupportingProtocols(userInfoInputArray); const isSearching = !!props.route.params.searching; @@ -297,8 +299,10 @@ searching: isSearching, userInfoInputArray, allUsersSupportThickThreads, + allUsersSupportFarcasterThreads, }), [ + allUsersSupportFarcasterThreads, allUsersSupportThickThreads, existingThreadInfoFinder, isSearching, @@ -366,14 +370,24 @@ const resolveToUser = React.useCallback( async (user: AccountUserInfo) => { const newUserInfoInputArray = user.id === viewerID ? [] : [user]; - const usersSupportingThickThreads = await checkUsersThickThreadSupport( - newUserInfoInputArray.map(userInfo => userInfo.id), - ); + const newUserIDs = newUserInfoInputArray.map(userInfo => userInfo.id); + const [usersSupportingThickThreads, usersSupportingFarcasterThreads] = + await Promise.all([ + checkUsersThickThreadSupport(newUserIDs), + checkUsersFarcasterDCsSupport(newUserIDs), + ]); + const resolvedThreadInfo = existingThreadInfoFinder({ searching: true, userInfoInputArray: newUserInfoInputArray, allUsersSupportThickThreads: - user.id === viewerID || usersSupportingThickThreads.has(user.id), + user.id === viewerID + ? true + : !!usersSupportingThickThreads.get(user.id), + allUsersSupportFarcasterThreads: + user.id === viewerID + ? false + : !!usersSupportingFarcasterThreads.get(user.id), }); invariant( resolvedThreadInfo, @@ -384,10 +398,11 @@ setParams({ searching: false, threadInfo: resolvedThreadInfo }); }, [ - checkUsersThickThreadSupport, viewerID, - editInputMessage, + checkUsersThickThreadSupport, + checkUsersFarcasterDCsSupport, existingThreadInfoFinder, + editInputMessage, setParams, ], ); diff --git a/web/chat/chat-thread-composer.react.js b/web/chat/chat-thread-composer.react.js --- a/web/chat/chat-thread-composer.react.js +++ b/web/chat/chat-thread-composer.react.js @@ -9,7 +9,10 @@ import SWMansionIcon from 'lib/components/swmansion-icon.react.js'; import { useLoggedInUserInfo } from 'lib/hooks/account-hooks.js'; import { useENSNames } from 'lib/hooks/ens-cache.js'; -import { useUsersSupportThickThreads } from 'lib/hooks/user-identities-hooks.js'; +import { + useUsersSupportFarcasterDCs, + useUsersSupportThickThreads, +} from 'lib/hooks/user-identities-hooks.js'; import { userInfoSelectorForPotentialMembers } from 'lib/selectors/user-selectors.js'; import { usePotentialMemberItems, @@ -92,6 +95,7 @@ ); const checkUsersThickThreadSupport = useUsersSupportThickThreads(); + const checkUsersFarcasterDCsSupport = useUsersSupportFarcasterDCs(); const onSelectUserFromSearch = React.useCallback( async (userListItem: UserListItem) => { @@ -106,9 +110,14 @@ username: userListItem.username, }; const newUserInfoInputArray = user.id === viewerID ? [] : [newUserInfo]; - const usersSupportingThickThreads = await checkUsersThickThreadSupport( - newUserInfoInputArray.map(userInfo => userInfo.id), - ); + const newUserIDs = newUserInfoInputArray.map(userInfo => userInfo.id); + + const [usersSupportingThickThreads, usersSupportingFarcasterThreads] = + await Promise.all([ + checkUsersThickThreadSupport(newUserIDs), + checkUsersFarcasterDCsSupport(newUserIDs), + ]); + const threadInfo = existingThreadInfoFinderForCreatingThread({ searching: true, userInfoInputArray: newUserInfoInputArray, @@ -116,6 +125,10 @@ user.id === viewerID ? true : !!usersSupportingThickThreads.get(user.id), + allUsersSupportFarcasterThreads: + user.id === viewerID + ? false + : !!usersSupportingFarcasterThreads.get(user.id), }); dispatch({ type: updateNavInfoActionType, @@ -137,12 +150,13 @@ } }, [ - checkUsersThickThreadSupport, - dispatch, viewerID, + userInfoInputArray, + checkUsersThickThreadSupport, + checkUsersFarcasterDCsSupport, existingThreadInfoFinderForCreatingThread, + dispatch, pushModal, - userInfoInputArray, ], ); diff --git a/web/utils/thread-utils.js b/web/utils/thread-utils.js --- a/web/utils/thread-utils.js +++ b/web/utils/thread-utils.js @@ -78,7 +78,7 @@ }); const existingThreadInfoFinder = useExistingThreadInfoFinder(baseThreadInfo); - const { allUsersSupportThickThreads } = + const { allUsersSupportThickThreads, allUsersSupportFarcasterThreads } = useUsersSupportingProtocols(selectedUserInfos); const threadInfo = React.useMemo(() => { @@ -91,6 +91,7 @@ searching: true, userInfoInputArray: selectedUserInfos, allUsersSupportThickThreads, + allUsersSupportFarcasterThreads, }); } @@ -98,8 +99,10 @@ searching: false, userInfoInputArray: [], allUsersSupportThickThreads: true, + allUsersSupportFarcasterThreads: true, }); }, [ + allUsersSupportFarcasterThreads, allUsersSupportThickThreads, existingThreadInfoFinder, existingThreadInfoFinderForCreatingThread,