Add debug message option to MessageContextMenu

This commit is contained in:
trevor-signal
2026-02-13 15:07:18 -05:00
committed by GitHub
parent cd29c96a89
commit 4a78b284e8
8 changed files with 38 additions and 0 deletions

View File

@@ -73,6 +73,7 @@ export const CallingNotification: React.FC<PropsType> = React.memo(
});
}}
shouldShowAdditional={false}
onDebugMessage={null}
onDownload={null}
onEdit={null}
onReplyToMessage={null}

View File

@@ -4,6 +4,7 @@
import React, { useRef, type ReactNode } from 'react';
import type { LocalizerType } from '../../types/I18N.std.js';
import { AxoMenuBuilder } from '../../axo/AxoMenuBuilder.dom.js';
import { isInternalFeaturesEnabled } from '../../util/isInternalFeaturesEnabled.dom.js';
type MessageContextMenuProps = Readonly<{
i18n: LocalizerType;
@@ -11,6 +12,7 @@ type MessageContextMenuProps = Readonly<{
onOpenChange?: (open: boolean) => void;
disabled?: boolean;
shouldShowAdditional: boolean;
onDebugMessage: (() => void) | null;
onDownload: (() => void) | null;
onEdit: (() => void) | null;
onReplyToMessage: (() => void) | null;
@@ -34,6 +36,7 @@ export function MessageContextMenu({
onOpenChange,
disabled,
shouldShowAdditional,
onDebugMessage,
onDownload,
onEdit,
onReplyToMessage,
@@ -162,6 +165,17 @@ export function MessageContextMenu({
{i18n('icu:retryDeleteForEveryone')}
</AxoMenuBuilder.Item>
)}
{isInternalFeaturesEnabled() && onDebugMessage && (
<>
<AxoMenuBuilder.Separator />
<AxoMenuBuilder.Group>
<AxoMenuBuilder.Label>Internal</AxoMenuBuilder.Label>
<AxoMenuBuilder.Item symbol="copy" onSelect={onDebugMessage}>
Copy & debug message
</AxoMenuBuilder.Item>
</AxoMenuBuilder.Group>
</>
)}
</AxoMenuBuilder.Content>
</AxoMenuBuilder.Root>
);

View File

@@ -112,6 +112,7 @@ const defaultMessageProps: TimelineMessagesProps = {
isSMS: false,
isSpoilerExpanded: {},
isVoiceMessagePlayed: false,
handleDebugMessage: action('debugMessage'),
toggleSelectMessage: action('toggleSelectMessage'),
cancelAttachmentDownload: action('default--cancelAttachmentDownload'),
kickOffAttachmentDownload: action('default--kickOffAttachmentDownload'),

View File

@@ -374,6 +374,7 @@ const renderItem = ({
containerWidthBreakpoint={containerWidthBreakpoint}
conversationId=""
item={items[messageId]}
handleDebugMessage={action('handleDebugMessage')}
renderAudioAttachment={() => <div>*AudioAttachment*</div>}
renderContact={() => <div>*ContactName*</div>}
renderReactionPicker={() => <div />}

View File

@@ -50,6 +50,7 @@ const getDefaultProps = () => ({
interactionMode: 'keyboard' as const,
theme: ThemeType.light,
platform: 'darwin',
handleDebugMessage: action('handleDebugMessage'),
targetMessage: action('targetMessage'),
toggleSelectMessage: action('toggleSelectMessage'),
endPoll: action('endPoll'),

View File

@@ -268,6 +268,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
expirationTimestamp: overrideProps.expirationTimestamp ?? 0,
getPreferredBadge: overrideProps.getPreferredBadge || (() => undefined),
giftBadge: overrideProps.giftBadge,
handleDebugMessage: action('handleDebugMessage'),
i18n,
platform: 'darwin',
id: overrideProps.id ?? 'random-message-id',

View File

@@ -86,6 +86,7 @@ export type PropsActions = {
messageId: string,
isPinningDisappearingMessage: boolean
) => void;
handleDebugMessage: () => void;
} & Omit<MessagePropsActions, 'onToggleSelect' | 'onReplyToMessage'>;
export type Props = PropsData &
@@ -125,6 +126,7 @@ export function TimelineMessage(props: Props): React.JSX.Element {
copyMessageText,
endPoll,
expirationLength,
handleDebugMessage,
onPinnedMessageRemove,
pushPanelForConversation,
reactToMessage,
@@ -367,6 +369,7 @@ export function TimelineMessage(props: Props): React.JSX.Element {
args: { messageId: id },
})
}
onDebugMessage={handleDebugMessage}
>
{children}
</MessageContextMenu>
@@ -383,6 +386,7 @@ export function TimelineMessage(props: Props): React.JSX.Element {
canRetryDeleteForEveryone,
conversationId,
copyMessageText,
handleDebugMessage,
handleDownload,
handleReact,
handleOpenPinMessageDialog,

View File

@@ -42,6 +42,8 @@ import { renderReactionPicker } from './renderReactionPicker.dom.js';
import type { MessageRequestState } from '../../components/conversation/MessageRequestActionsConfirmation.dom.js';
import { TargetedMessageSource } from '../ducks/conversationsEnums.std.js';
import type { MessageInteractivity } from '../../components/conversation/Message.dom.js';
import { DataReader } from '../../sql/Client.preload.js';
import { isInternalFeaturesEnabled } from '../../util/isInternalFeaturesEnabled.dom.js';
export type SmartTimelineItemProps = {
containerElementRef: RefObject<HTMLElement>;
@@ -195,6 +197,18 @@ export const SmartTimelineItem = memo(function SmartTimelineItem(
[conversationId, toggleMessageRequestActionsConfirmation]
);
const handleDebugMessage = useCallback(async () => {
if (!isInternalFeaturesEnabled()) {
return;
}
const message = await DataReader.getMessageById(messageId);
// eslint-disable-next-line no-console
console.debug(message);
await window.navigator.clipboard.writeText(
JSON.stringify(message, null, 2)
);
}, [messageId]);
return (
<TimelineItem
item={item}
@@ -235,6 +249,7 @@ export const SmartTimelineItem = memo(function SmartTimelineItem(
endPoll={endPoll}
reactToMessage={reactToMessage}
copyMessageText={copyMessageText}
handleDebugMessage={handleDebugMessage}
onOpenEditNicknameAndNoteModal={onOpenEditNicknameAndNoteModal}
onOpenMessageRequestActionsConfirmation={
onOpenMessageRequestActionsConfirmation