Page MenuHomePhorge

D15526.1765026673.diff
No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None

D15526.1765026673.diff

diff --git a/lib/hooks/input-state-container-hooks.js b/lib/hooks/input-state-container-hooks.js
--- a/lib/hooks/input-state-container-hooks.js
+++ b/lib/hooks/input-state-container-hooks.js
@@ -18,6 +18,7 @@
import { messageTypes } from '../types/message-types-enum.js';
import type {
RawMultimediaMessageInfo,
+ ReplyParameters,
SendMessagePayload,
SendMultimediaMessagePayload,
} from '../types/message-types.js';
@@ -31,6 +32,7 @@
parentThreadInfo: ?ThreadInfo,
sidebarCreation: boolean,
threadCreation: boolean,
+ reply?: ?ReplyParameters,
) => Promise<SendMessagePayload> {
const sendKeyserverTextMessage = useSendTextMessage();
const sendComposableDMOperation = useSendComposableDMOperation();
@@ -49,6 +51,7 @@
parentThreadInfo: ?ThreadInfo,
sidebarCreation: boolean,
threadCreation: boolean,
+ reply?: ?ReplyParameters,
) => {
invariant(viewerID, 'Viewer ID should be present');
return threadSpecs[threadInfo.type].protocol().sendTextMessage(
@@ -58,6 +61,7 @@
parentThreadInfo,
sidebarCreation,
threadCreation,
+ reply,
},
{
sendKeyserverTextMessage,
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
@@ -37,8 +37,9 @@
| {
+groupId: string,
+message: string,
+ +inReplyToMessageId?: string,
}
- | { +recipientFid: number, +message: string };
+ | { +recipientFid: number, +message: string, +inReplyToMessageId?: string };
type SendFarcasterMessageResultData = {
+messageId: string,
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
@@ -23,6 +23,7 @@
import {
defaultNumberPerThread,
messageTruncationStatus,
+ type ReplyParameters,
type SendMessagePayload,
type SendMultimediaMessagePayload,
} from '../../../types/message-types.js';
@@ -126,6 +127,7 @@
rawThreadInfos,
farcasterFetchConversation,
threadCreation,
+ reply,
}: {
threadInfo: ThreadInfo | RawThreadInfo,
viewerID: string,
@@ -137,9 +139,17 @@
conversationID: string,
) => Promise<?FarcasterConversation>,
threadCreation: boolean,
+ reply?: ?ReplyParameters,
}) {
const time = Date.now();
+ let messageText = text;
+ let targetMessageID = null;
+ if (reply && text.startsWith(reply.messagePrefix)) {
+ messageText = text.slice(reply.messagePrefix.length);
+ targetMessageID = reply.targetMessageID;
+ }
+
let request;
if (threadInfo.type === farcasterThreadTypes.FARCASTER_PERSONAL) {
const otherUser = getSingleOtherUser(threadInfo, viewerID);
@@ -158,13 +168,15 @@
const recipientFID = parseInt(targetFID, 10);
request = {
recipientFid: recipientFID,
- message: text,
+ message: messageText,
+ ...(targetMessageID ? { inReplyToMessageId: targetMessageID } : {}),
};
} else {
const conversationID = conversationIDFromFarcasterThreadID(threadInfo.id);
request = {
groupId: conversationID,
- message: text,
+ message: messageText,
+ ...(targetMessageID ? { inReplyToMessageId: targetMessageID } : {}),
};
}
@@ -193,7 +205,7 @@
farcasterFetchConversation,
rawThreadInfos,
} = utils;
- const { messageInfo, threadInfo, threadCreation } = message;
+ const { messageInfo, threadInfo, threadCreation, reply } = message;
const { localID } = messageInfo;
invariant(
localID !== null && localID !== undefined,
@@ -209,6 +221,7 @@
rawThreadInfos,
farcasterFetchConversation,
threadCreation,
+ reply,
});
return {
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
@@ -57,6 +57,7 @@
FetchPinnedMessagesResult,
RawMessageInfo,
MessageInfo,
+ ReplyParameters,
} from '../../types/message-types.js';
import type { RawTextMessageInfo } from '../../types/messages/text.js';
import type {
@@ -132,6 +133,7 @@
+parentThreadInfo: ?ThreadInfo,
+sidebarCreation: boolean,
+threadCreation: boolean,
+ +reply?: ?ReplyParameters,
};
export type SendTextMessageUtils = {
+sendKeyserverTextMessage: SendTextMessageInput => Promise<SendMessageResult>,
diff --git a/lib/types/message-types.js b/lib/types/message-types.js
--- a/lib/types/message-types.js
+++ b/lib/types/message-types.js
@@ -224,6 +224,11 @@
// Raw*MessageInfo = used by server, and contained in client's local store
// *MessageInfo = used by client in UI code
+export type ReplyParameters = {
+ +targetMessageID: string,
+ +messagePrefix: string,
+};
+
export type ValidRawSidebarSourceMessageInfo =
| RawTextMessageInfo
| RawCreateThreadMessageInfo
diff --git a/native/chat/composed-message.react.js b/native/chat/composed-message.react.js
--- a/native/chat/composed-message.react.js
+++ b/native/chat/composed-message.react.js
@@ -13,6 +13,7 @@
import { chatMessageItemHasEngagement } from 'lib/shared/chat-message-item-utils.js';
import { getMessageLabel } from 'lib/shared/edit-messages-utils.js';
+import { messageID } from 'lib/shared/id-utils.js';
import { createMessageReply } from 'lib/shared/markdown.js';
import { assertComposableMessageType } from 'lib/types/message-types.js';
@@ -159,15 +160,15 @@
sendFailed,
]);
- const editInputMessage = inputState?.editInputMessage;
const reply = React.useCallback(() => {
- invariant(editInputMessage, 'editInputMessage should be set in reply');
+ invariant(inputState, 'Input state should be set in reply');
invariant(item.messageInfo.text, 'text should be set in reply');
- editInputMessage({
- message: createMessageReply(item.messageInfo.text),
- mode: 'prepend',
+ const messagePrefix = createMessageReply(item.messageInfo.text);
+ inputState.replyToMessage({
+ targetMessageID: messageID(item.messageInfo),
+ messagePrefix,
});
- }, [editInputMessage, item.messageInfo.text]);
+ }, [inputState, item.messageInfo]);
const triggerReply =
swipeOptions === 'reply' || swipeOptions === 'both' ? reply : undefined;
diff --git a/native/chat/text-message-tooltip-modal.react.js b/native/chat/text-message-tooltip-modal.react.js
--- a/native/chat/text-message-tooltip-modal.react.js
+++ b/native/chat/text-message-tooltip-modal.react.js
@@ -4,6 +4,7 @@
import invariant from 'invariant';
import * as React from 'react';
+import { messageID } from 'lib/shared/id-utils.js';
import { createMessageReply } from 'lib/shared/markdown.js';
import { useDeleteMessage } from 'lib/utils/delete-message-utils.js';
@@ -51,11 +52,17 @@
'inputState should be set in TextMessageTooltipModal.onPressReply',
);
navigateToThread({ threadInfo });
- inputState.editInputMessage({
- message: createMessageReply(text),
- mode: 'prepend',
+ inputState.replyToMessage({
+ targetMessageID: messageID(route.params.item.messageInfo),
+ messagePrefix: createMessageReply(text),
});
- }, [inputState, navigateToThread, threadInfo, text]);
+ }, [
+ inputState,
+ navigateToThread,
+ route.params.item.messageInfo,
+ text,
+ threadInfo,
+ ]);
const renderReplyIcon = React.useCallback(
(style: TextStyle) => <CommIcon name="reply" style={style} size={12} />,
[],
diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js
--- a/native/input/input-state-container.react.js
+++ b/native/input/input-state-container.react.js
@@ -73,6 +73,7 @@
import {
type RawMessageInfo,
type RawMultimediaMessageInfo,
+ type ReplyParameters,
type SendMessagePayload,
type SendMultimediaMessagePayload,
} from 'lib/types/message-types.js';
@@ -165,6 +166,7 @@
parentThreadInfo: ?ThreadInfo,
sidebarCreation: boolean,
threadCreation: boolean,
+ reply?: ?ReplyParameters,
) => Promise<SendMessagePayload>,
+newThinThread: (
request: ClientNewThinThreadRequest,
@@ -181,11 +183,13 @@
};
type State = {
+pendingUploads: PendingMultimediaUploads,
+ +reply: ?ReplyParameters,
};
class InputStateContainer extends React.PureComponent<Props, State> {
state: State = {
pendingUploads: {},
+ reply: null,
};
sendCallbacks: Array<() => void> = [];
activeURIs: Map<string, ActiveURI> = new Map();
@@ -436,6 +440,7 @@
sendTextMessage: this.sendTextMessage,
sendMultimediaMessage: this.sendMultimediaMessage,
editInputMessage: this.editInputMessage,
+ replyToMessage: this.replyToMessage,
addEditInputMessageListener: this.addEditInputMessageListener,
removeEditInputMessageListener: this.removeEditInputMessageListener,
messageHasUploadFailure: this.messageHasUploadFailure,
@@ -622,6 +627,8 @@
const sidebarCreation =
this.pendingSidebarCreationMessageLocalIDs.has(localID);
+ const reply = this.state.reply;
+
try {
const result = await this.props.sendTextMessage(
messageInfo,
@@ -629,8 +636,10 @@
parentThreadInfo,
sidebarCreation,
threadCreation,
+ reply,
);
this.pendingSidebarCreationMessageLocalIDs.delete(localID);
+ this.setState({ reply: null });
return result;
} catch (e) {
if (e instanceof SendMessageError) {
@@ -1371,6 +1380,16 @@
);
};
+ replyToMessage = (params: ReplyParameters) => {
+ this.editInputMessage({
+ message: params.messagePrefix,
+ mode: 'prepend',
+ });
+ this.setState({
+ reply: params,
+ });
+ };
+
addEditInputMessageListener = (
callbackEditInputBar: (params: EditInputBarMessageParameters) => void,
) => {
diff --git a/native/input/input-state.js b/native/input/input-state.js
--- a/native/input/input-state.js
+++ b/native/input/input-state.js
@@ -3,6 +3,7 @@
import * as React from 'react';
import type { NativeMediaSelection } from 'lib/types/media-types.js';
+import type { ReplyParameters } from 'lib/types/message-types.js';
import type { RawTextMessageInfo } from 'lib/types/messages/text.js';
import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
@@ -39,6 +40,7 @@
threadInfo: ThreadInfo,
) => Promise<void>,
+editInputMessage: (params: EditInputBarMessageParameters) => void,
+ +replyToMessage: (params: ReplyParameters) => void,
+addEditInputMessageListener: (
(params: EditInputBarMessageParameters) => void,
) => void,
diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js
--- a/web/input/input-state-container.react.js
+++ b/web/input/input-state-container.react.js
@@ -74,6 +74,7 @@
type RawMultimediaMessageInfo,
type SendMessagePayload,
type SendMultimediaMessagePayload,
+ type ReplyParameters,
} from 'lib/types/message-types.js';
import type { RawImagesMessageInfo } from 'lib/types/messages/images.js';
import type { RawMediaMessageInfo } from 'lib/types/messages/media.js';
@@ -155,6 +156,7 @@
parentThreadInfo: ?ThreadInfo,
sidebarCreation: boolean,
threadCreation: boolean,
+ reply?: ?ReplyParameters,
) => Promise<SendMessagePayload>,
+newThinThread: (
request: ClientNewThinThreadRequest,
@@ -180,6 +182,7 @@
},
textCursorPositions: { [threadID: string]: number },
typeaheadState: TypeaheadState,
+ reply: ?ReplyParameters,
};
type State = $ReadOnly<WritableState>;
@@ -202,6 +205,7 @@
close: null,
accept: null,
},
+ reply: null,
};
replyCallbacks: Array<(message: string) => void> = [];
pendingThreadCreations: Map<
@@ -690,7 +694,7 @@
threadInfo,
assignedUploads[localMessageID],
),
- addReply: (message: string) => this.addReply(message),
+ addReply: (params: ReplyParameters) => this.addReply(params),
addReplyListener: this.addReplyListener,
removeReplyListener: this.removeReplyListener,
registerSendCallback: this.props.registerSendCallback,
@@ -1420,6 +1424,8 @@
const sidebarCreation =
this.pendingSidebarCreationMessageLocalIDs.has(localID);
+ const reply = this.state.reply;
+
try {
const result = await this.props.sendTextMessage(
messageInfo,
@@ -1427,8 +1433,10 @@
parentThreadInfo,
sidebarCreation,
threadCreation,
+ reply,
);
this.pendingSidebarCreationMessageLocalIDs.delete(localID);
+ this.setState({ reply: null });
return result;
} catch (e) {
if (e instanceof SendMessageError) {
@@ -1659,8 +1667,11 @@
void this.uploadFiles(threadInfo, uploadsToRetry);
}
- addReply = (message: string) => {
- this.replyCallbacks.forEach(addReplyCallback => addReplyCallback(message));
+ addReply = (params: ReplyParameters) => {
+ this.replyCallbacks.forEach(addReplyCallback =>
+ addReplyCallback(params.messagePrefix),
+ );
+ this.setState({ reply: params });
};
addReplyListener = (callbackReply: (message: string) => void) => {
diff --git a/web/input/input-state.js b/web/input/input-state.js
--- a/web/input/input-state.js
+++ b/web/input/input-state.js
@@ -8,6 +8,7 @@
type MediaMissionStep,
type MediaType,
} from 'lib/types/media-types.js';
+import type { ReplyParameters } from 'lib/types/message-types.js';
import type { RawTextMessageInfo } from 'lib/types/messages/text.js';
import type {
RelativeMemberInfo,
@@ -80,7 +81,7 @@
localMessageID: string,
threadInfo: ThreadInfo,
) => void,
- +addReply: (text: string) => void,
+ +addReply: (params: ReplyParameters) => void,
+addReplyListener: ((message: string) => void) => void,
+removeReplyListener: ((message: string) => void) => void,
+registerSendCallback: (() => mixed) => void,
diff --git a/web/tooltips/tooltip-action-utils.js b/web/tooltips/tooltip-action-utils.js
--- a/web/tooltips/tooltip-action-utils.js
+++ b/web/tooltips/tooltip-action-utils.js
@@ -17,6 +17,7 @@
chatMessageItemEngagementTargetMessageInfo,
} from 'lib/shared/chat-message-item-utils.js';
import { useCanEditMessage } from 'lib/shared/edit-messages-utils.js';
+import { messageID } from 'lib/shared/id-utils.js';
import { createMessageReply } from 'lib/shared/markdown.js';
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
import { useSidebarExistsOrCanBeCreated } from 'lib/shared/sidebar-utils.js';
@@ -209,7 +210,10 @@
if (!messageInfo.text) {
return;
}
- addReply(createMessageReply(messageInfo.text));
+ addReply({
+ targetMessageID: messageID(messageInfo),
+ messagePrefix: createMessageReply(messageInfo.text),
+ });
};
return {
actionButtonContent: buttonContent,

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 6, 1:11 PM (16 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5837863
Default Alt Text
D15526.1765026673.diff (14 KB)

Event Timeline