Page MenuHomePhorge

D15498.1765011396.diff
No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None

D15498.1765011396.diff

diff --git a/lib/selectors/chat-selectors.js b/lib/selectors/chat-selectors.js
--- a/lib/selectors/chat-selectors.js
+++ b/lib/selectors/chat-selectors.js
@@ -29,7 +29,10 @@
type SidebarItem,
} from '../shared/sidebar-item-utils.js';
import { threadInChatList, threadIsPending } from '../shared/thread-utils.js';
-import { threadTypeIsSidebar } from '../shared/threads/thread-specs.js';
+import {
+ threadSpecs,
+ threadTypeIsSidebar,
+} from '../shared/threads/thread-specs.js';
import { messageTypes } from '../types/message-types-enum.js';
import {
type ComposableMessageInfo,
@@ -450,22 +453,29 @@
targetMessageEditMap.set(messageInfo.targetMessageID, messageInfo.text);
}
+ const threadInfo = threadInfos[threadID];
const targetMessagePinStatusMap = new Map<string, boolean>();
- // Once again, we iterate backwards to put the order of messages in
- // chronological order (i.e. oldest to newest) to handle pinned messages.
- // This is important because we want to make sure that the most recent pin
- // action is the one that is used to determine whether a message
- // is pinned or not.
- for (let i = messages.length - 1; i >= 0; i--) {
- const messageInfo = messages[i];
- if (messageInfo.type !== messageTypes.TOGGLE_PIN) {
- continue;
- }
+ if (threadSpecs[threadInfo.type].protocol().pinsStoredOnServer) {
+ // Once again, we iterate backwards to put the order of messages in
+ // chronological order (i.e. oldest to newest) to handle pinned messages.
+ // This is important because we want to make sure that the most recent pin
+ // action is the one that is used to determine whether a message
+ // is pinned or not.
+ for (let i = messages.length - 1; i >= 0; i--) {
+ const messageInfo = messages[i];
+ if (messageInfo.type !== messageTypes.TOGGLE_PIN) {
+ continue;
+ }
- targetMessagePinStatusMap.set(
- messageInfo.targetMessageID,
- messageInfo.action === 'pin',
- );
+ targetMessagePinStatusMap.set(
+ messageInfo.targetMessageID,
+ messageInfo.action === 'pin',
+ );
+ }
+ } else {
+ for (const messageID of threadInfo.pinnedMessageIDs ?? []) {
+ targetMessagePinStatusMap.set(messageID, true);
+ }
}
const targetMessageDeleteStatusMap = new Map<string, boolean>();
@@ -602,7 +612,6 @@
return result;
})();
- const threadInfo = threadInfos[threadID];
const parentThreadInfo = threadInfo?.parentThreadID
? threadInfos[threadInfo.parentThreadID]
: null;
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
@@ -925,6 +925,40 @@
);
}
+export type PinMessageInput = {
+ +conversationId: string,
+ +messageId: string,
+};
+
+function usePinMessage(): (input: PinMessageInput) => Promise<void> {
+ const { sendFarcasterRequest } = useTunnelbroker();
+ const { addLog } = useDebugLogs();
+ return React.useCallback(
+ async (input: PinMessageInput) => {
+ try {
+ await sendFarcasterRequest({
+ apiVersion: 'v2',
+ endpoint: 'direct-cast-pin-message',
+ method: { type: 'POST' },
+ payload: JSON.stringify(input),
+ });
+ } catch (error) {
+ addLog(
+ 'Farcaster API: Failed to pin a message',
+ JSON.stringify({
+ conversationId: input.conversationId,
+ messageId: input.messageId,
+ error: getMessageForException(error),
+ }),
+ new Set([logTypes.FARCASTER, logTypes.ERROR]),
+ );
+ throw error;
+ }
+ },
+ [addLog, sendFarcasterRequest],
+ );
+}
+
export {
useSendFarcasterTextMessage,
useFetchFarcasterMessages,
@@ -942,4 +976,5 @@
useAcceptInvite,
useFetchFarcasterConversationInvites,
useAcceptOneOnOneInvite,
+ usePinMessage,
};
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
@@ -429,6 +429,8 @@
+farcasterConversation: FarcasterConversation,
+thread: FarcasterRawThreadInfo,
+threadMembers: Array<MemberInfoSansPermissions>,
+ +pinnedMessages: Array<RawMessageInfo>,
+ +userIDs: Array<string>,
};
async function fetchAndProcessConversation(
conversationID: string,
@@ -553,10 +555,23 @@
members: threadMembers,
};
+ const userFIDs = farcasterConversation.pinnedMessages.flatMap(message =>
+ extractFarcasterIDsFromPayload(farcasterMessageValidator, message),
+ );
+ const fetchedUserInfos = await fetchUsersByFIDs(userFIDs);
+ const pinnedMessages = farcasterConversation.pinnedMessages.flatMap(message =>
+ convertFarcasterMessageToCommMessages(message, fetchedUserInfos, addLog),
+ );
+ const userIDs = Array.from(fetchedUserInfos.entries()).map(
+ ([fid, user]) => user?.userID ?? userIDFromFID(fid),
+ );
+
return {
farcasterConversation,
thread,
threadMembers,
+ pinnedMessages,
+ userIDs,
};
}
@@ -615,6 +630,8 @@
threadMembers.forEach(member => batchedUpdates.addUserID(member.id));
}
batchedUpdates.addUpdateInfo(update);
+ batchedUpdates.addAdditionalMessageInfos(result.pinnedMessages);
+ batchedUpdates.addUserIDs(result.userIDs);
return farcasterConversation;
} catch (e) {
@@ -735,6 +752,8 @@
rawEntryInfos: [],
};
batchedUpdates.addUpdateInfo(update);
+ batchedUpdates.addAdditionalMessageInfos(result.pinnedMessages);
+ batchedUpdates.addUserIDs(result.userIDs);
return farcasterConversation;
} catch (e) {
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
@@ -952,6 +952,14 @@
if (pinnedCount) {
threadInfo = { ...threadInfo, pinnedCount };
}
+
+ if (rawThreadInfo.pinnedMessageIDs) {
+ threadInfo = {
+ ...threadInfo,
+ pinnedMessageIDs: rawThreadInfo.pinnedMessageIDs,
+ };
+ }
+
return threadInfo;
}
diff --git a/lib/shared/threads/protocols/dm-thread-protocol.js b/lib/shared/threads/protocols/dm-thread-protocol.js
--- a/lib/shared/threads/protocols/dm-thread-protocol.js
+++ b/lib/shared/threads/protocols/dm-thread-protocol.js
@@ -954,6 +954,7 @@
supportsThreadRefreshing: false,
supportsMessageEdit: true,
supportsRelationships: true,
+ pinsStoredOnServer: false,
});
function pendingThreadType(numberOfOtherMembers: number) {
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
@@ -726,6 +726,13 @@
};
}
+ if (clientDBThreadInfo.pinnedMessageIDs) {
+ rawThreadInfo = {
+ ...rawThreadInfo,
+ pinnedMessageIDs: JSON.parse(clientDBThreadInfo.pinnedMessageIDs),
+ };
+ }
+
return rawThreadInfo;
},
@@ -1032,10 +1039,11 @@
supportsThreadRefreshing: true,
temporarilyDisabledFeatures: {
changingThreadAvatar: true,
- pinningMessages: true,
+ pinningMessages: false,
},
supportsMessageEdit: false,
supportsRelationships: false,
+ pinsStoredOnServer: false,
};
function pendingThreadType(numberOfOtherMembers: number) {
diff --git a/lib/shared/threads/protocols/keyserver-thread-protocol.js b/lib/shared/threads/protocols/keyserver-thread-protocol.js
--- a/lib/shared/threads/protocols/keyserver-thread-protocol.js
+++ b/lib/shared/threads/protocols/keyserver-thread-protocol.js
@@ -757,6 +757,7 @@
supportsThreadRefreshing: false,
supportsMessageEdit: true,
supportsRelationships: true,
+ pinsStoredOnServer: true,
});
function pendingThreadType(numberOfOtherMembers: number) {
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
@@ -559,6 +559,7 @@
},
+supportsMessageEdit: boolean,
+supportsRelationships: boolean,
+ +pinsStoredOnServer: boolean,
};
export type ThreadSpec<
diff --git a/lib/types/minimally-encoded-thread-permissions-types.js b/lib/types/minimally-encoded-thread-permissions-types.js
--- a/lib/types/minimally-encoded-thread-permissions-types.js
+++ b/lib/types/minimally-encoded-thread-permissions-types.js
@@ -279,6 +279,7 @@
+sourceMessageID?: string,
+repliesCount: number,
+pinnedCount?: number,
+ +pinnedMessageIDs?: $ReadOnlyArray<string>,
}>;
export type ResolvedThreadInfo = $ReadOnly<{
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
@@ -193,6 +193,7 @@
+currentUser: LegacyThreadCurrentUserInfo,
+repliesCount: number,
+pinnedCount?: number,
+ +pinnedMessageIDs?: $ReadOnlyArray<string>,
};
export type LegacyRawThreadInfo =
@@ -271,6 +272,7 @@
currentUser: legacyThreadCurrentUserInfoValidator,
repliesCount: t.Number,
pinnedCount: t.maybe(t.Number),
+ pinnedMessageIDs: t.maybe(t.list(tID)),
});
export const legacyThreadInfoValidator: TUnion<
@@ -347,6 +349,7 @@
+repliesCount: number,
+pinnedCount?: number,
+timestamps?: ?string,
+ +pinnedMessageIDs?: ?string,
};
export type ThreadDeletionRequest = {
diff --git a/lib/utils/convert-farcaster-message-to-comm-messages.js b/lib/utils/convert-farcaster-message-to-comm-messages.js
--- a/lib/utils/convert-farcaster-message-to-comm-messages.js
+++ b/lib/utils/convert-farcaster-message-to-comm-messages.js
@@ -23,7 +23,7 @@
function convertFarcasterMessageToCommMessages(
farcasterMessage: FarcasterMessage,
fcUserInfos: FCUserInfos,
- addLog: AddLogCallback,
+ addLog: ?AddLogCallback,
): $ReadOnlyArray<RawMessageInfo> {
const senderFid = farcasterMessage.senderFid.toString();
const creatorID =
@@ -194,8 +194,19 @@
time: parseInt(farcasterMessage.serverTimestamp, 10),
removedUserIDs: [removedUserID],
});
+ } else if (farcasterMessage.type === 'pin_message') {
+ result.push({
+ type: messageTypes.TOGGLE_PIN,
+ id: farcasterMessage.messageId,
+ threadID,
+ targetMessageID: farcasterMessage.message,
+ action: 'pin',
+ pinnedContent: 'a message',
+ creatorID,
+ time: parseInt(farcasterMessage.serverTimestamp, 10),
+ });
} else {
- addLog(
+ addLog?.(
'Unsupported Farcaster message',
`Unsupported message type: ${farcasterMessage.type}`,
new Set([logTypes.FARCASTER]),
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
@@ -14,8 +14,8 @@
import { generatePendingThreadColor } from '../shared/color-utils.js';
import type {
FarcasterConversation,
- FarcasterInboxConversation,
FarcasterConversationInvitee,
+ FarcasterInboxConversation,
} from '../shared/farcaster/farcaster-conversation-types.js';
import {
farcasterThreadIDFromConversationID,
@@ -38,8 +38,8 @@
minimallyEncodeThreadCurrentUserInfo,
} from '../types/minimally-encoded-thread-permissions-types.js';
import type { ThreadRolePermissionsBlob } from '../types/thread-permission-types.js';
-import { farcasterThreadTypes } from '../types/thread-types-enum.js';
import type { FarcasterThreadType } from '../types/thread-types-enum.js';
+import { farcasterThreadTypes } from '../types/thread-types-enum.js';
function createPermissionsInfo(
permissionsBlob: ThreadRolePermissionsBlob,
@@ -69,6 +69,7 @@
+description: string,
+createdAt: number,
+pinnedCount: number,
+ +pinnedMessageIDs: $ReadOnlyArray<string>,
+avatar: ?ClientAvatar,
+category: 'default' | 'archived' | 'request',
};
@@ -224,6 +225,7 @@
members,
roles,
currentUser,
+ pinnedMessageIDs: threadData.pinnedMessageIDs,
};
}
@@ -264,6 +266,10 @@
? ensNameForFarcasterUsername(otherUserName)
: 'anonymous';
}
+ const pinnedMessageIDs = conversation.pinnedMessages.map(
+ message => message.messageId,
+ );
+
const threadData: FarcasterThreadData = {
threadID,
isGroup: conversation.isGroup,
@@ -277,6 +283,7 @@
unread,
createdAt: conversation.createdAt,
pinnedCount: conversation.pinnedMessages.length,
+ pinnedMessageIDs,
avatar,
name,
description,
@@ -315,6 +322,7 @@
pinnedCount: threadInfo.pinnedCount ?? 0,
avatar: null,
category: 'default',
+ pinnedMessageIDs: threadInfo.pinnedMessageIDs ?? [],
};
return innerCreateFarcasterRawThreadInfo(threadData);
diff --git a/lib/utils/thread-ops-utils.js b/lib/utils/thread-ops-utils.js
--- a/lib/utils/thread-ops-utils.js
+++ b/lib/utils/thread-ops-utils.js
@@ -44,6 +44,9 @@
timestamps: rawThreadInfo.timestamps
? JSON.stringify(rawThreadInfo.timestamps)
: null,
+ pinnedMessageIDs: rawThreadInfo.pinnedMessageIDs
+ ? JSON.stringify(rawThreadInfo.pinnedMessageIDs)
+ : null,
};
}
diff --git a/lib/utils/thread-ops-utils.test.js b/lib/utils/thread-ops-utils.test.js
--- a/lib/utils/thread-ops-utils.test.js
+++ b/lib/utils/thread-ops-utils.test.js
@@ -386,6 +386,7 @@
avatar: null,
pinnedCount: 0,
timestamps: null,
+ pinnedMessageIDs: null,
};
describe('convertRawThreadInfoToClientDBThreadInfo', () => {

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 6, 8:56 AM (11 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5834239
Default Alt Text
D15498.1765011396.diff (13 KB)

Event Timeline