diff --git a/lib/hooks/thread-hooks.js b/lib/hooks/thread-hooks.js --- a/lib/hooks/thread-hooks.js +++ b/lib/hooks/thread-hooks.js @@ -568,6 +568,8 @@ ); const keyserverLeaveThread = useKeyserverCall(leaveThread); const dispatchActionPromise = useDispatchActionPromise(); + const modifyFarcasterMembership = useModifyFarcasterMembershipInput(); + const auxUserStore = useSelector(state => state.auxUserStore); return React.useCallback( (input: UseLeaveThreadInput) => @@ -577,11 +579,15 @@ processAndSendDMOperation, keyserverLeaveThread, dispatchActionPromise, + modifyFarcasterMembership, + auxUserStore, }, ), [ + auxUserStore, dispatchActionPromise, keyserverLeaveThread, + modifyFarcasterMembership, processAndSendDMOperation, viewerID, ], diff --git a/lib/shared/threads/protocols/farcaster-thread-protocol.js b/lib/shared/threads/protocols/farcaster-thread-protocol.js --- a/lib/shared/threads/protocols/farcaster-thread-protocol.js +++ b/lib/shared/threads/protocols/farcaster-thread-protocol.js @@ -5,8 +5,10 @@ import { fetchMessagesBeforeCursorActionTypes } from '../../../actions/message-actions.js'; import { changeThreadMemberRolesActionTypes, + leaveThreadActionTypes, removeUsersFromThreadActionTypes, } from '../../../actions/thread-action-types.js'; +import type { LeaveThreadResult } from '../../../hooks/thread-hooks.js'; import { getFarcasterRolePermissionsBlobs } from '../../../permissions/farcaster-permissions.js'; import type { RolePermissionBlobs } from '../../../permissions/thread-permissions.js'; import type { SetThreadUnreadStatusPayload } from '../../../types/activity-types.js'; @@ -85,6 +87,8 @@ ChangeThreadMemberRolesUtils, ProtocolRemoveUsersFromThreadInput, RemoveUsersFromThreadUtils, + ProtocolLeaveThreadInput, + LeaveThreadUtils, } from '../thread-spec.js'; const farcasterThreadProtocol: ThreadProtocol = { @@ -430,8 +434,57 @@ }; }, - leaveThread: async () => { - throw new Error('leaveThread method is not yet implemented'); + leaveThread: async ( + input: ProtocolLeaveThreadInput, + utils: LeaveThreadUtils, + ): Promise => { + const { threadInfo, viewerID } = input; + const { modifyFarcasterMembership, dispatchActionPromise, auxUserStore } = + utils; + + const conversationId = conversationIDFromFarcasterThreadID(threadInfo.id); + + const promise = (async () => { + if (viewerID) { + const viewerFID = + auxUserStore.auxUserInfos[viewerID]?.fid ?? + extractFIDFromUserID(viewerID); + + if (viewerFID) { + const modifyFarcasterMembershipInput: ModifyFarcasterMembershipInput = + { + conversationId, + action: 'remove', + targetFid: parseInt(viewerFID, 10), + }; + + await modifyFarcasterMembership(modifyFarcasterMembershipInput); + } + } + + return { + updatesResult: { + newUpdates: [ + { + type: updateTypes.DELETE_THREAD, + threadID: threadInfo.id, + id: threadInfo.id, + time: Date.now(), + }, + ], + }, + }; + })(); + + const customKeyName = `${leaveThreadActionTypes.started}:${threadInfo.id}`; + void dispatchActionPromise(leaveThreadActionTypes, promise, { + customKeyName, + }); + await promise; + + return { + invalidatedThreads: [threadInfo.id], + }; }, convertClientDBThreadInfo: ( diff --git a/lib/shared/threads/thread-spec.js b/lib/shared/threads/thread-spec.js --- a/lib/shared/threads/thread-spec.js +++ b/lib/shared/threads/thread-spec.js @@ -288,6 +288,10 @@ +processAndSendDMOperation: OutboundDMOperationSpecification => Promise, +keyserverLeaveThread: LeaveThreadInput => Promise, +dispatchActionPromise: DispatchActionPromise, + +modifyFarcasterMembership: ( + input: ModifyFarcasterMembershipInput, + ) => Promise, + +auxUserStore: AuxUserStore, }; export type ProtocolFetchMessageInput = {