Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32162136
D15337.1765044642.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D15337.1765044642.diff
View Options
diff --git a/lib/shared/reaction-utils.js b/lib/shared/reaction-utils.js
--- a/lib/shared/reaction-utils.js
+++ b/lib/shared/reaction-utils.js
@@ -10,18 +10,20 @@
import { useThreadHasPermission } from './thread-utils.js';
import { threadSpecs } from './threads/thread-specs.js';
import { stringForUserExplicit } from './user-utils.js';
+import { useGetLatestMessageEdit } from '../hooks/latest-message-edit.js';
import { useSendReactionMessage } from '../hooks/message-hooks.js';
import { useResolvableNames } from '../hooks/names-cache.js';
import type { ReactionInfo } from '../selectors/chat-selectors.js';
import type {
ComposableMessageInfo,
+ MessageInfo,
RobotextMessageInfo,
} from '../types/message-types.js';
import { isComposableMessageType } from '../types/message-types.js';
import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
import { threadPermissions } from '../types/thread-permission-types.js';
import { useDispatchActionPromise } from '../utils/redux-promise-utils.js';
-import { useSelector } from '../utils/redux-utils.js';
+import { useDispatch, useSelector } from '../utils/redux-utils.js';
function useViewerAlreadySelectedMessageReactions(
reactions: ReactionInfo,
@@ -116,7 +118,7 @@
}
function useSendReactionBase(
- messageID: ?string,
+ messageInfo: ?MessageInfo,
threadInfo: ThreadInfo,
reactions: ReactionInfo,
showErrorAlert: () => mixed,
@@ -129,10 +131,12 @@
const dispatchActionPromise = useDispatchActionPromise();
const processAndSendDMOperation = useProcessAndSendDMOperation();
const farcasterSendReaction = useSendFarcasterReaction();
+ const dispatch = useDispatch();
+ const fetchMessage = useGetLatestMessageEdit();
return React.useCallback(
reaction => {
- if (!messageID) {
+ if (!messageInfo) {
return;
}
@@ -145,7 +149,7 @@
void threadSpecs[threadInfo.type].protocol().sendReaction(
{
- messageID,
+ messageInfo,
threadInfo,
reaction,
action,
@@ -157,19 +161,23 @@
keyserverSendReaction: callSendReactionMessage,
dispatchActionPromise,
farcasterSendReaction,
+ dispatch,
+ fetchMessage,
},
);
},
[
- messageID,
- viewerID,
- reactions,
- threadInfo,
- showErrorAlert,
- processAndSendDMOperation,
callSendReactionMessage,
+ dispatch,
dispatchActionPromise,
farcasterSendReaction,
+ fetchMessage,
+ messageInfo,
+ processAndSendDMOperation,
+ reactions,
+ showErrorAlert,
+ threadInfo,
+ viewerID,
],
);
}
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
@@ -520,8 +520,12 @@
input: ProtocolSendReactionInput,
utils: SendReactionUtils,
) => {
- const { threadInfo, viewerID, messageID, reaction, action } = input;
+ const { threadInfo, viewerID, messageInfo, reaction, action } = input;
const threadID = threadInfo.id;
+ const messageID = messageInfo.id;
+ if (!messageID) {
+ return;
+ }
const op: DMSendReactionMessageOperation = {
type: 'send_reaction_message',
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
@@ -18,11 +18,13 @@
DeleteEntryResult,
SaveEntryResult,
} from '../../../types/entry-types.js';
+import { messageTypes } from '../../../types/message-types-enum.js';
import {
defaultNumberPerThread,
type SendMessagePayload,
type SendMultimediaMessagePayload,
} from '../../../types/message-types.js';
+import type { CompoundReactionInfo } from '../../../types/messages/compound-reaction.js';
import type {
FarcasterRawThreadInfo,
MemberInfoSansPermissions,
@@ -46,8 +48,10 @@
ThreadJoinPayload,
} from '../../../types/thread-types.js';
import { updateTypes } from '../../../types/update-types-enum.js';
+import { messageIDToCompoundReactionID } from '../../../utils/convert-farcaster-message-to-comm-messages.js';
import { farcasterThreadIDRegExp } from '../../../utils/validation-utils.js';
import { generatePendingThreadColor } from '../../color-utils.js';
+import { processFarcasterOpsActionType } from '../../farcaster/farcaster-actions.js';
import {
type ModifyFarcasterMembershipInput,
type SendReactionInput,
@@ -326,8 +330,56 @@
input: ProtocolSendReactionInput,
utils: SendReactionUtils,
) => {
- const { threadInfo, reaction, action, messageID } = input;
+ const { threadInfo, reaction, action, messageInfo } = input;
const conversationId = conversationIDFromFarcasterThreadID(threadInfo.id);
+ const messageID = messageInfo.id;
+ if (!messageID) {
+ return;
+ }
+
+ const reactionsMessageID = messageIDToCompoundReactionID(messageID);
+ const currentReactionsMessage =
+ await utils.fetchMessage(reactionsMessageID);
+ const reactionCountChange = action === 'add_reaction' ? 1 : -1;
+ let currentCount = 0;
+ if (
+ currentReactionsMessage &&
+ currentReactionsMessage.type === messageTypes.COMPOUND_REACTION
+ ) {
+ currentCount = currentReactionsMessage.reactions[reaction]?.count ?? 0;
+ }
+
+ const newCount = currentCount + reactionCountChange;
+ const updatedReaction = {
+ count: currentCount + reactionCountChange,
+ viewerReacted: action === 'add_reaction',
+ };
+ const { [reaction]: oldReaction, ...rest } =
+ (currentReactionsMessage?.reactions ?? {}: {
+ +[reaction: string]: CompoundReactionInfo,
+ });
+ let updatedReactions = rest;
+ if (newCount > 0) {
+ updatedReactions = {
+ ...currentReactionsMessage?.reactions,
+ [reaction]: updatedReaction,
+ };
+ }
+
+ const updatedMessage = {
+ id: reactionsMessageID,
+ type: messageTypes.COMPOUND_REACTION,
+ threadID: threadInfo.id,
+ creatorID: messageInfo.creator.id,
+ time: messageInfo.time + 1,
+ targetMessageID: messageID,
+ reactions: updatedReactions,
+ };
+ utils.dispatch({
+ type: processFarcasterOpsActionType,
+ payload: { rawMessageInfos: [updatedMessage], updateInfos: [] },
+ });
+
const payload: SendReactionInput = {
conversationId,
messageId: messageID,
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
@@ -302,13 +302,17 @@
const {
threadInfo,
viewerID,
- messageID,
+ messageInfo,
reaction,
action,
showErrorAlert,
} = input;
const threadID = threadInfo.id;
const localID = getNextLocalID();
+ const messageID = messageInfo.id;
+ if (!messageID) {
+ return;
+ }
const reactionMessagePromise = (async () => {
try {
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
@@ -53,6 +53,8 @@
FetchMessageInfosPayload,
DeleteMessageRequest,
DeleteMessageResponse,
+ RawMessageInfo,
+ MessageInfo,
} from '../../types/message-types.js';
import type { RawTextMessageInfo } from '../../types/messages/text.js';
import type {
@@ -213,7 +215,7 @@
};
export type ProtocolSendReactionInput = {
- +messageID: string,
+ +messageInfo: MessageInfo,
+threadInfo: ThreadInfo,
+reaction: string,
+action: 'remove_reaction' | 'add_reaction',
@@ -225,6 +227,8 @@
+keyserverSendReaction: SendReactionMessageRequest => Promise<SendMessageResult>,
+farcasterSendReaction: SendReactionInput => Promise<void>,
+dispatchActionPromise: DispatchActionPromise,
+ +dispatch: Dispatch,
+ +fetchMessage: (messageID: string) => Promise<?RawMessageInfo>,
};
export type ProtocolAddThreadMembersInput = {
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
@@ -13,6 +13,10 @@
import type { RawMessageInfo } from '../types/message-types.js';
import type { CompoundReactionInfo } from '../types/messages/compound-reaction.js';
+function messageIDToCompoundReactionID(messageID: string): string {
+ return `${messageID}/reactions`;
+}
+
function convertFarcasterMessageToCommMessages(
farcasterMessage: FarcasterMessage,
fcUserInfos: FCUserInfos,
@@ -38,7 +42,7 @@
};
}
result.push({
- id: `${farcasterMessage.messageId}/reactions`,
+ id: messageIDToCompoundReactionID(farcasterMessage.messageId),
type: messageTypes.COMPOUND_REACTION,
threadID,
// Doesn't matter - we don't use it
@@ -210,4 +214,4 @@
.replaceAll('%3D', '=');
}
-export { convertFarcasterMessageToCommMessages };
+export { convertFarcasterMessageToCommMessages, messageIDToCompoundReactionID };
diff --git a/native/chat/inline-engagement.react.js b/native/chat/inline-engagement.react.js
--- a/native/chat/inline-engagement.react.js
+++ b/native/chat/inline-engagement.react.js
@@ -251,7 +251,7 @@
repliesText,
]);
- const sendReaction = useSendReaction(messageInfo.id, threadInfo, reactions);
+ const sendReaction = useSendReaction(messageInfo, threadInfo, reactions);
const onPressReaction = React.useCallback(
(reaction: string) => sendReaction(reaction),
diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js
--- a/native/chat/multimedia-message-tooltip-button.react.js
+++ b/native/chat/multimedia-message-tooltip-button.react.js
@@ -112,7 +112,7 @@
messageInfo,
);
- const sendReaction = useSendReaction(messageInfo.id, threadInfo, reactions);
+ const sendReaction = useSendReaction(messageInfo, threadInfo, reactions);
const [emojiPickerOpen, setEmojiPickerOpen] = React.useState<boolean>(false);
const openEmojiPicker = React.useCallback(() => {
diff --git a/native/chat/reaction-message-utils.js b/native/chat/reaction-message-utils.js
--- a/native/chat/reaction-message-utils.js
+++ b/native/chat/reaction-message-utils.js
@@ -4,6 +4,7 @@
import type { ReactionInfo } from 'lib/selectors/chat-selectors.js';
import { useSendReactionBase } from 'lib/shared/reaction-utils.js';
+import type { MessageInfo } from 'lib/types/message-types.js';
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types';
import { useSelector } from '../redux/redux-utils.js';
@@ -25,12 +26,12 @@
}
function useSendReaction(
- messageID: ?string,
+ messageInfo: ?MessageInfo,
threadInfo: ThreadInfo,
reactions: ReactionInfo,
): (reaction: string) => mixed {
return useSendReactionBase(
- messageID,
+ messageInfo,
threadInfo,
reactions,
showReactionErrorAlert,
diff --git a/native/chat/robotext-message-tooltip-button.react.js b/native/chat/robotext-message-tooltip-button.react.js
--- a/native/chat/robotext-message-tooltip-button.react.js
+++ b/native/chat/robotext-message-tooltip-button.react.js
@@ -81,7 +81,7 @@
);
const sendReaction = useSendReaction(
- engagementTargetMessageInfo?.id,
+ engagementTargetMessageInfo,
threadInfo,
reactions,
);
diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js
--- a/native/chat/text-message-tooltip-button.react.js
+++ b/native/chat/text-message-tooltip-button.react.js
@@ -109,7 +109,7 @@
messageInfo,
);
- const sendReaction = useSendReaction(messageInfo.id, threadInfo, reactions);
+ const sendReaction = useSendReaction(messageInfo, threadInfo, reactions);
const [emojiPickerOpen, setEmojiPickerOpen] = React.useState<boolean>(false);
const openEmojiPicker = React.useCallback(() => {
diff --git a/web/chat/inline-engagement.react.js b/web/chat/inline-engagement.react.js
--- a/web/chat/inline-engagement.react.js
+++ b/web/chat/inline-engagement.react.js
@@ -88,12 +88,12 @@
<ReactionPill
key={reaction}
reaction={reaction}
- messageID={messageInfo.id}
+ messageInfo={messageInfo}
threadInfo={threadInfo}
reactions={reactions}
/>
));
- }, [reactions, deleted, messageInfo.id, threadInfo]);
+ }, [reactions, deleted, messageInfo, threadInfo]);
const containerClasses = classNames([
css.inlineEngagementContainer,
diff --git a/web/chat/reaction-message-utils.js b/web/chat/reaction-message-utils.js
--- a/web/chat/reaction-message-utils.js
+++ b/web/chat/reaction-message-utils.js
@@ -5,6 +5,7 @@
import { useModalContext } from 'lib/components/modal-provider.react.js';
import type { ReactionInfo } from 'lib/selectors/chat-selectors.js';
import { useSendReactionBase } from 'lib/shared/reaction-utils.js';
+import type { MessageInfo } from 'lib/types/message-types.js';
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
import Alert from '../modals/alert.react.js';
@@ -15,7 +16,7 @@
import { getAppContainerPositionInfo } from '../utils/window-utils.js';
function useSendReaction(
- messageID: ?string,
+ messageInfo: ?MessageInfo,
threadInfo: ThreadInfo,
reactions: ReactionInfo,
): (reaction: string) => mixed {
@@ -30,7 +31,12 @@
),
[pushModal],
);
- return useSendReactionBase(messageID, threadInfo, reactions, showErrorAlert);
+ return useSendReactionBase(
+ messageInfo,
+ threadInfo,
+ reactions,
+ showErrorAlert,
+ );
}
type EmojiKeyboardPosition = {
diff --git a/web/chat/reaction-pill.react.js b/web/chat/reaction-pill.react.js
--- a/web/chat/reaction-pill.react.js
+++ b/web/chat/reaction-pill.react.js
@@ -4,6 +4,7 @@
import * as React from 'react';
import type { ReactionInfo } from 'lib/selectors/chat-selectors.js';
+import type { MessageInfo } from 'lib/types/message-types.js';
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
import { useSendReaction } from './reaction-message-utils.js';
@@ -18,15 +19,15 @@
type Props = {
+reaction: string,
- +messageID: ?string,
+ +messageInfo: MessageInfo,
+threadInfo: ThreadInfo,
+reactions: ReactionInfo,
};
function ReactionPill(props: Props): React.Node {
- const { reaction, messageID, threadInfo, reactions } = props;
+ const { reaction, messageInfo, threadInfo, reactions } = props;
- const sendReaction = useSendReaction(messageID, threadInfo, reactions);
+ const sendReaction = useSendReaction(messageInfo, threadInfo, reactions);
const onClickReaction = React.useCallback(
(event: SyntheticEvent<HTMLElement>) => {
diff --git a/web/tooltips/message-tooltip.react.js b/web/tooltips/message-tooltip.react.js
--- a/web/tooltips/message-tooltip.react.js
+++ b/web/tooltips/message-tooltip.react.js
@@ -173,7 +173,7 @@
const engagementTargetMessageInfo =
chatMessageItemEngagementTargetMessageInfo(item);
const sendReaction = useSendReaction(
- engagementTargetMessageInfo?.id,
+ engagementTargetMessageInfo,
threadInfo,
reactions,
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 6, 6:10 PM (16 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5840023
Default Alt Text
D15337.1765044642.diff (15 KB)
Attached To
Mode
D15337: [lib] Optimistically create a reaction
Attached
Detach File
Event Timeline
Log In to Comment