diff --git a/lib/permissions/farcaster-permissions.js b/lib/permissions/farcaster-permissions.js --- a/lib/permissions/farcaster-permissions.js +++ b/lib/permissions/farcaster-permissions.js @@ -3,6 +3,7 @@ import type { RolePermissionBlobs } from './thread-permissions.js'; import type { FarcasterConversation } from '../shared/farcaster/farcaster-conversation-types.js'; import { threadPermissions } from '../types/thread-permission-types.js'; +import type { ThreadRolePermissionsBlob } from '../types/thread-permission-types.js'; import type { FarcasterThreadType } from '../types/thread-types-enum.js'; import { farcasterThreadTypes } from '../types/thread-types-enum.js'; @@ -86,7 +87,16 @@ } } +function nonMemberPermissions(): ThreadRolePermissionsBlob { + return { + [threadPermissions.KNOW_OF]: true, + [threadPermissions.VISIBLE]: true, + [threadPermissions.JOIN_THREAD]: true, + }; +} + export { getFarcasterRolePermissionsBlobsFromConversation, getFarcasterRolePermissionsBlobs, + nonMemberPermissions, }; diff --git a/lib/shared/farcaster/farcaster-hooks.js b/lib/shared/farcaster/farcaster-hooks.js --- a/lib/shared/farcaster/farcaster-hooks.js +++ b/lib/shared/farcaster/farcaster-hooks.js @@ -668,7 +668,11 @@ onProgress?: (completed: number, total: number) => void, ) => { try { - const inboxResults = await Promise.all([fetchInboxes()]); + const inboxResults = await Promise.all([ + fetchInboxes(), + fetchInboxes('request'), + fetchInboxes('archived'), + ]); const conversations = inboxResults.flat(); removeDeadThreads(conversations); @@ -743,7 +747,11 @@ async (onProgress?: (completed: number, total: number) => void) => { try { invariant(currentUserFID, 'currentUserFID is not defined'); - const inboxResults = await Promise.all([fetchInboxes()]); + const inboxResults = await Promise.all([ + fetchInboxes(), + fetchInboxes('request'), + fetchInboxes('archived'), + ]); const conversations = inboxResults.flat(); const conversationIDs = conversations.map( conversation => conversation.conversationId, 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 @@ -243,8 +243,11 @@ function threadInChatList( threadInfo: ?(LegacyRawThreadInfo | RawThreadInfo | ThreadInfo), ): boolean { + const isFarcaster = threadInfo?.type + ? threadSpecs[threadInfo.type].protocol().protocolName === 'Farcaster DC' + : false; return ( - viewerIsMember(threadInfo) && + (viewerIsMember(threadInfo) || isFarcaster) && threadHasPermission(threadInfo, threadPermissions.VISIBLE) ); } diff --git a/lib/utils/create-farcaster-raw-thread-info.js b/lib/utils/create-farcaster-raw-thread-info.js --- a/lib/utils/create-farcaster-raw-thread-info.js +++ b/lib/utils/create-farcaster-raw-thread-info.js @@ -4,6 +4,7 @@ import { getFarcasterRolePermissionsBlobs, getFarcasterRolePermissionsBlobsFromConversation, + nonMemberPermissions, } from '../permissions/farcaster-permissions.js'; import { specialRoles } from '../permissions/special-roles.js'; import { @@ -63,6 +64,7 @@ +createdAt: number, +pinnedCount: number, +avatar: ?ClientAvatar, + +category: 'default' | 'archived' | 'request', }; function createMembersAndCurrentUser(options: { @@ -79,6 +81,7 @@ +muted: boolean, }, +threadType: FarcasterThreadType, + +category: 'default' | 'archived' | 'request', }) { const { threadID, @@ -125,18 +128,22 @@ role: adminIDs.has(fid) && adminsRole ? adminsRole.id : membersRole.id, })); - const currentUserRole = - currentUserOptions.isAdmin && adminsRole ? adminsRole : membersRole; + let currentUserRole = null; + let permissionsBlob; + if (options.category === 'request') { + permissionsBlob = nonMemberPermissions(); + } else { + currentUserRole = + currentUserOptions.isAdmin && adminsRole ? adminsRole : membersRole; + permissionsBlob = + currentUserOptions.isAdmin && permissionBlobs.Admins + ? permissionBlobs.Admins + : permissionBlobs.Members; + } const currentUser: ThreadCurrentUserInfo = minimallyEncodeThreadCurrentUserInfo({ - role: currentUserRole.id, - permissions: createPermissionsInfo( - currentUserOptions.isAdmin && permissionBlobs.Admins - ? permissionBlobs.Admins - : permissionBlobs.Members, - threadID, - threadType, - ), + role: currentUserRole?.id, + permissions: createPermissionsInfo(permissionsBlob, threadID, threadType), subscription: { home: !currentUserOptions.muted, pushNotifs: !currentUserOptions.muted, @@ -166,6 +173,7 @@ muted: threadData.muted, }, threadType, + category: threadData.category, }); return { @@ -238,6 +246,7 @@ avatar, name, description, + category: conversation.viewerContext.category, }; return innerCreateFarcasterRawThreadInfo(threadData); @@ -270,6 +279,7 @@ createdAt: threadInfo.creationTime, pinnedCount: threadInfo.pinnedCount ?? 0, avatar: null, + category: 'default', }; return innerCreateFarcasterRawThreadInfo(threadData); @@ -295,7 +305,7 @@ }; } - let avatarURI = null; + let avatarURI; if (conversation.isGroup) { avatarURI = conversation.photoUrl; } else { @@ -314,7 +324,11 @@ conversation.viewerContext.unreadCount > 0 || conversation.viewerContext.manuallyMarkedUnread; - if (conversation.isGroup) { + if ( + conversation.isGroup || + (!threadInfo.currentUser.role && + conversation.viewerContext.category !== 'request') + ) { const adminIDs = new Set(conversation.adminFids.map(fid => `${fid}`)); const adminsRole = values(threadInfo.roles).find( role => role.specialRole === specialRoles.ADMIN_ROLE, @@ -343,6 +357,7 @@ muted: conversation.viewerContext.muted, }, threadType: threadTypes.FARCASTER_GROUP, + category: conversation.viewerContext.category, }); updatedThreadInfo = { ...updatedThreadInfo,