Page MenuHomePhorge

D15291.1764995470.diff
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

D15291.1764995470.diff

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
@@ -20,7 +20,9 @@
useFetchFarcasterConversation,
useFetchFarcasterMessages,
useUpdateFarcasterGroupNameAndDescription,
+ useModifyFarcasterMembershipInput,
} from '../shared/farcaster/farcaster-api.js';
+import { useFetchConversation } from '../shared/farcaster/farcaster-hooks.js';
import { threadSpecs } from '../shared/threads/thread-specs.js';
import { permissionsAndAuthRelatedRequestTimeout } from '../shared/timeouts.js';
import type {
@@ -349,6 +351,9 @@
) => Promise<ChangeThreadSettingsPayload> {
const keyserverCall = useKeyserverCall(changeThreadMemberRoles);
const dispatchActionPromise = useDispatchActionPromise();
+ const modifyFarcasterMembership = useModifyFarcasterMembershipInput();
+ const fetchConversation = useFetchConversation();
+ const auxUserStore = useSelector(state => state.auxUserStore);
return React.useCallback(
async (input: ChangeThreadMemberRolesInput) => {
const { threadInfo, memberIDs, newRole } = input;
@@ -367,10 +372,19 @@
{
keyserverCall,
dispatchActionPromise,
+ modifyFarcasterMembership,
+ fetchConversation,
+ auxUserStore,
},
);
},
- [dispatchActionPromise, keyserverCall],
+ [
+ dispatchActionPromise,
+ keyserverCall,
+ modifyFarcasterMembership,
+ fetchConversation,
+ auxUserStore,
+ ],
);
}
diff --git a/lib/shared/farcaster/farcaster-api.js b/lib/shared/farcaster/farcaster-api.js
--- a/lib/shared/farcaster/farcaster-api.js
+++ b/lib/shared/farcaster/farcaster-api.js
@@ -414,6 +414,55 @@
);
}
+export type ModifyFarcasterMembershipInput =
+ | {
+ +conversationId: string,
+ +action: 'demote',
+ +targetFid: number,
+ }
+ | {
+ +conversationId: string,
+ +action: 'promote',
+ +targetFid: number,
+ }
+ | {
+ +conversationId: string,
+ +action: 'remove',
+ +targetFid: number,
+ }
+ | {
+ +conversationId: string,
+ +action: 'add',
+ +inviteCode: string,
+ }
+ | {
+ +conversationId: string,
+ +action: 'add',
+ +targetFid: number,
+ }
+ | {
+ +conversationId: string,
+ +action: 'add',
+ +targetFids: $ReadOnlyArray<number>,
+ };
+
+function useModifyFarcasterMembershipInput(): (
+ input: ModifyFarcasterMembershipInput,
+) => Promise<void> {
+ const { sendFarcasterRequest } = useTunnelbroker();
+ return React.useCallback(
+ async (input: ModifyFarcasterMembershipInput) => {
+ await sendFarcasterRequest({
+ apiVersion: 'v2',
+ endpoint: 'direct-cast-group-membership',
+ method: { type: 'POST' },
+ payload: JSON.stringify(input),
+ });
+ },
+ [sendFarcasterRequest],
+ );
+}
+
export {
useSendFarcasterTextMessage,
useFetchFarcasterMessages,
@@ -424,4 +473,5 @@
useStreamFarcasterDirectCastRead,
useMarkFarcasterDirectCastUnread,
useCreateFarcasterGroup,
+ useModifyFarcasterMembershipInput,
};
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
@@ -3,6 +3,7 @@
import invariant from 'invariant';
import { fetchMessagesBeforeCursorActionTypes } from '../../../actions/message-actions.js';
+import { changeThreadMemberRolesActionTypes } from '../../../actions/thread-action-types.js';
import { getFarcasterRolePermissionsBlobs } from '../../../permissions/farcaster-permissions.js';
import type { RolePermissionBlobs } from '../../../permissions/thread-permissions.js';
import type { SetThreadUnreadStatusPayload } from '../../../types/activity-types.js';
@@ -45,6 +46,7 @@
import { createFarcasterRawThreadInfo } from '../../../utils/create-farcaster-raw-thread-info.js';
import { farcasterThreadIDRegExp } from '../../../utils/validation-utils.js';
import { generatePendingThreadColor } from '../../color-utils.js';
+import { type ModifyFarcasterMembershipInput } from '../../farcaster/farcaster-api.js';
import { farcasterMessageValidator } from '../../farcaster/farcaster-messages-types.js';
import {
conversationIDFromFarcasterThreadID,
@@ -58,6 +60,7 @@
getSingleOtherUser,
threadIsPending,
threadOtherMembers,
+ roleIsAdminRole,
} from '../../thread-utils.js';
import type {
ChangeThreadSettingsUtils,
@@ -75,6 +78,8 @@
UpdateSubscriptionUtils,
ProtocolCreatePendingThreadInput,
CreateRealThreadParameters,
+ ProtocolChangeThreadMemberRolesInput,
+ ChangeThreadMemberRolesUtils,
} from '../thread-spec.js';
const farcasterThreadProtocol: ThreadProtocol<MemberInfoSansPermissions> = {
@@ -277,6 +282,67 @@
throw new Error('addThreadMembers method is not yet implemented');
},
+ changeThreadMemberRoles: async (
+ input: ProtocolChangeThreadMemberRolesInput,
+ utils: ChangeThreadMemberRolesUtils,
+ ): Promise<ChangeThreadSettingsPayload> => {
+ const { threadInfo, memberIDs, newRole } = input;
+ const {
+ modifyFarcasterMembership,
+ fetchConversation,
+ dispatchActionPromise,
+ auxUserStore,
+ } = utils;
+
+ const conversationId = conversationIDFromFarcasterThreadID(threadInfo.id);
+
+ // Determine if we're promoting or demoting based on role
+ const isPromoting = roleIsAdminRole(threadInfo.roles[newRole]);
+
+ const promise = (async () => {
+ const membershipPromises = memberIDs
+ .map(memberID => {
+ const targetFid =
+ auxUserStore.auxUserInfos[memberID]?.fid ??
+ extractFIDFromUserID(memberID);
+ if (targetFid) {
+ let modifyFarcasterMembershipInput: ModifyFarcasterMembershipInput =
+ {
+ conversationId,
+ action: 'demote',
+ targetFid: parseInt(targetFid, 10),
+ };
+
+ if (isPromoting) {
+ modifyFarcasterMembershipInput = {
+ conversationId,
+ action: 'promote',
+ targetFid: parseInt(targetFid, 10),
+ };
+ }
+
+ return modifyFarcasterMembership(modifyFarcasterMembershipInput);
+ }
+ return null;
+ })
+ .filter(Boolean);
+
+ await Promise.all(membershipPromises);
+
+ await fetchConversation(conversationId);
+
+ return {
+ threadID: threadInfo.id,
+ updatesResult: { newUpdates: [] },
+ newMessageInfos: [],
+ };
+ })();
+
+ void dispatchActionPromise(changeThreadMemberRolesActionTypes, promise);
+
+ return await promise;
+ },
+
updateSubscription: async (
protocolInput: ProtocolUpdateSubscriptionInput,
utils: UpdateSubscriptionUtils,
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
@@ -99,6 +99,7 @@
MarkFarcasterDirectCastUnreadInput,
CreateFarcasterGroupResult,
CreateFarcasterGroupInput,
+ ModifyFarcasterMembershipInput,
} from '../farcaster/farcaster-api.js';
import type { FarcasterConversation } from '../farcaster/farcaster-conversation-types.js';
import type { FetchMessagesFromDBType } from '../message-utils.js';
@@ -246,6 +247,11 @@
export type ChangeThreadMemberRolesUtils = {
+keyserverCall: ProtocolChangeThreadMemberRolesInput => Promise<ChangeThreadSettingsPayload>,
+dispatchActionPromise: DispatchActionPromise,
+ +modifyFarcasterMembership: (
+ input: ModifyFarcasterMembershipInput,
+ ) => Promise<void>,
+ +fetchConversation: (conversationId: string) => Promise<mixed>,
+ +auxUserStore: AuxUserStore,
};
export type ProtocolUpdateSubscriptionInput = {

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 6, 4:31 AM (7 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5832159
Default Alt Text
D15291.1764995470.diff (7 KB)

Event Timeline