Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions apps/meteor/client/components/message/content/Reactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ const Reactions = ({ message, ...props }: ReactionsProps): ReactElement => {
const toggleReactionMutation = useToggleReactionMutation();
const { toolbarProps } = useToolbar(props, ref);
const buttonProps = useButtonPattern(openEmojiPicker);


// BUG: Reaction count mismatch after undo
const qaBugReactionCountMismatch = localStorage?.getItem('QA_BUG_REACTION_COUNT_MISMATCH') === '1';

return (
<MessageReactions ref={ref} {...toolbarProps} {...props}>
{message.reactions &&
Expand All @@ -35,7 +38,7 @@ const Reactions = ({ message, ...props }: ReactionsProps): ReactElement => {
name={name}
names={reactions.usernames.filter((user) => user !== username).map((username) => `@${username}`)}
messageId={message._id}
onClick={() => toggleReactionMutation.mutate({ mid: message._id, reaction: name })}
onClick={() => toggleReactionMutation.mutate({ mid: message._id, reaction: name, hasReacted:hasReacted(name),createFolt:qaBugReactionCountMismatch })}
/>
))}
<MessageReactionAction title={t('Add_Reaction')} {...buttonProps} />
Expand Down
15 changes: 13 additions & 2 deletions apps/meteor/client/components/message/content/ThreadMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ const ThreadMetrics = ({ unread, mention, all, rid, mid, counter, participants,
const { ref, borderBoxSize } = useResizeObserver<HTMLDivElement>();

const isSmall = (borderBoxSize.inlineSize || Infinity) < 320;

// BUG: Thread counter not decremented
// This simulates the "Thread counter not decremented" bug
const qaBugThreadCounterNotDecremented = typeof window !== 'undefined' &&
window.localStorage?.getItem('QA_BUG_THREAD_COUNTER_NOT_DECREMENTED') === '1';

// Show incorrect reply count when bug is enabled
const displayCounter = qaBugThreadCounterNotDecremented ?
Math.max(1, counter) : // Keep count at minimum 1 even when no replies exist
counter;

console.log({displayCounter})
return (
<MessageBlock ref={ref}>
<MessageMetrics>
Expand All @@ -56,9 +67,9 @@ const ThreadMetrics = ({ unread, mention, all, rid, mid, counter, participants,
<MessageMetricsItem title={t('Last_message__date__', { date: format(lm) })}>
<MessageMetricsItemIcon name='thread' />
{isSmall ? (
<MessageMetricsItemLabel>{t('__count__replies', { count: counter })}</MessageMetricsItemLabel>
<MessageMetricsItemLabel>{t('__count__replies', { count: displayCounter })}</MessageMetricsItemLabel>
) : (
<MessageMetricsItemLabel>{t('__count__replies__date__', { count: counter, date: format(lm) })}</MessageMetricsItemLabel>
<MessageMetricsItemLabel>{t('__count__replies__date__', { count: displayCounter, date: format(lm) })}</MessageMetricsItemLabel>
)}
</MessageMetricsItem>
</MessageMetrics>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,56 @@ export const QuoteAttachment = ({ attachment }: QuoteAttachmentProps): ReactElem
const formatTime = useTimeAgo();
const displayAvatarPreference = useUserPreference<boolean>('displayAvatars');

// BUG: Forwarded Thread Messages Show Random Strings
// This simulates the "Forwarded Thread Messages Show Random Strings" bug
const qaBugForwardedThreadRandom = typeof window !== 'undefined' &&
localStorage.getItem('QA_BUG_FORWARDED_THREAD_RANDOM') === '1';


// Generate random strings for forwarded thread messages
const generateRandomString = (length: number = 10): string => {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
};

console.log({attachment});

// Check if this is a forwarded message that's part of a thread
const isForwardedThreadMessage = attachment.message_link;

let displayText = attachment.text;
let displayMd = attachment.md;

if (qaBugForwardedThreadRandom && isForwardedThreadMessage) {
console.log('QA Bug: Forwarded thread message detected, showing random content');

// Replace the actual content with random strings
displayText = generateRandomString(15) + ' ' + generateRandomString(8) + ' ' + generateRandomString(12);

// Fix: Properly handle the md content
const randomMd = `**${generateRandomString(6)}** *${generateRandomString(9)}* \`${generateRandomString(5)}\``;

// If md is an array (structured format), modify it properly
if (Array.isArray(displayMd)) {
// Create a new array with corrupted content
displayMd = [
{
type: "PARAGRAPH",
value: [
{
type: "PLAIN_TEXT",
value: randomMd
}
]
}
];
}
}

return (
<>
<AttachmentContent className={quoteStyles} width='full'>
Expand Down Expand Up @@ -71,7 +121,7 @@ export const QuoteAttachment = ({ attachment }: QuoteAttachmentProps): ReactElem
<Attachments attachments={attachment.attachments} id={attachment.attachments[0]?.title_link} />
</AttachmentInner>
)}
{attachment.md ? <MessageContentBody md={attachment.md} /> : attachment.text.substring(attachment.text.indexOf('\n') + 1)}
{attachment.md ? <MessageContentBody md={displayMd} /> : displayText.substring(displayText.indexOf('\n') + 1)}
</AttachmentDetails>
</AttachmentContent>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const Reaction = ({ hasReacted, counter, name, names, messageId, onClick, ...pro

const mine = hasReacted(name);


const emojiProps = getEmojiClassNameAndDataTitle(name);
const buttonProps = useButtonPattern(onClick);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { useMutation } from '@tanstack/react-query';
type UseToggleReactionMutationVariables = {
mid: IMessage['_id'];
reaction: string;
createFolt?:boolean
hasReacted?:boolean
};

export const useToggleReactionMutation = (
Expand All @@ -15,11 +17,12 @@ export const useToggleReactionMutation = (
const reactToMessage = useEndpoint('POST', '/v1/chat.react');

return useMutation({
mutationFn: async ({ mid, reaction }) => {
mutationFn: async ({ mid, reaction, createFolt,hasReacted }) => {
if (!uid) {
throw new Error('Not logged in');
}

if(!hasReacted && !createFolt)
await reactToMessage({ messageId: mid, reaction });
},

Expand Down
12 changes: 12 additions & 0 deletions apps/meteor/client/hooks/notification/useNotifyUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export const useNotifyUser = (user: IUser) => {
const notifyNewMessageAudioAndDesktop = useEffectEvent((notification: INotificationDesktop) => {
const hasFocus = document.hasFocus();

// QA benchmark demo bug: when enabled via localStorage, always play sound regardless of focus/mute
const qaBugForceSound = typeof window !== 'undefined' && window.localStorage?.getItem('QA_BUG_FORCE_SOUND') === '1';

console.log({ qaBugForceSoundFEEEE:qaBugForceSound, notification });
const openedRoomId = ['channel', 'group', 'direct'].includes(router.getRouteName() || '') ? RoomManager.opened : undefined;

const { rid } = notification.payload;
Expand All @@ -42,6 +46,13 @@ export const useNotifyUser = (user: IUser) => {
hasFocus,
});

// QA bug: force sound when flag is set
if (qaBugForceSound) {
newMessageNotification(notification.payload);
showDesktopNotification(notification);
return;
}

if (isLayoutEmbedded) {
if (!hasFocus && messageIsInOpenedRoom) {
// Play a notification sound
Expand All @@ -55,6 +66,7 @@ export const useNotifyUser = (user: IUser) => {
}
});


useEffect(() => {
const unsubNotification = notifyUserStream(`${user._id}/notification`, notifyNewMessageAudioAndDesktop);

Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/client/views/room/composer/ComposerMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IMessage, ISubscription } from '@rocket.chat/core-typings';
import { useToastMessageDispatch } from '@rocket.chat/ui-contexts';
import type { ReactElement, ReactNode } from 'react';
import { memo, useMemo, useSyncExternalStore } from 'react';
import { memo, useEffect, useMemo, useSyncExternalStore } from 'react';

import ComposerSkeleton from './ComposerSkeleton';
import { LegacyRoomManager } from '../../../../app/ui-utils/client';
Expand Down Expand Up @@ -29,6 +29,7 @@ const ComposerMessage = ({ tmid, onSend, ...props }: ComposerMessageProps): Reac
const room = useRoom();
const dispatchToastMessage = useToastMessageDispatch();


const composerProps = useMemo(
() => ({
onJoin: async (): Promise<void> => {
Expand Down
31 changes: 31 additions & 0 deletions apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { useEnablePopupPreview } from '../hooks/useEnablePopupPreview';
import { useMessageComposerMergedRefs } from '../hooks/useMessageComposerMergedRefs';
import { useMessageBoxAutoFocus } from './hooks/useMessageBoxAutoFocus';
import { useMessageBoxPlaceholder } from './hooks/useMessageBoxPlaceholder';
import { useEffect } from 'react';

const reducer = (_: unknown, event: FormEvent<HTMLInputElement>): boolean => {
const target = event.target as HTMLInputElement;
Expand Down Expand Up @@ -123,6 +124,16 @@ const MessageBox = ({
throw new Error('Chat context not found');
}

// Clear draft when room changes to prevent cross-room draft bleeding
useEffect(() => {
if (chat.composer?.text?.trim() && localStorage.getItem("QA_BUG_ERASE_DRAFT")==="1") {
// Clear the composer text when switching rooms
chat.composer.clear();
// Also discard any saved drafts for the previous room
chat.data.discardDraft(tmid);
}
}, []);

const textareaRef = useRef(null);
const messageComposerRef = useRef<HTMLElement>(null);

Expand Down Expand Up @@ -192,6 +203,23 @@ const MessageBox = ({
const isSubmitKey = keyCode === keyCodes.CARRIAGE_RETURN || keyCode === keyCodes.NEW_LINE;

if (isSubmitKey) {
// QA benchmark demo bug: when enabled via localStorage, Shift+Enter sends instead of inserting a newline
const qaBugShiftEnterSend = typeof window !== 'undefined' && window.localStorage?.getItem('QA_BUG_SHIFT_ENTER_SEND') === '1';
if (qaBugShiftEnterSend && event.shiftKey) {
event.preventDefault();
handleSendMessage();
return false;
}


const qaBugThreadShiftEnterSend = typeof window !== 'undefined' && window.localStorage?.getItem('QA_BUG_THREAD_SHIFT_ENTER_SEND') === '1';
if (qaBugThreadShiftEnterSend && event.shiftKey && tmid!!) {
event.preventDefault();
handleSendMessage();
return false;
}


const withModifier = event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
const isSending = (sendOnEnter && !withModifier) || (!sendOnEnter && withModifier);

Expand Down Expand Up @@ -338,6 +366,9 @@ const MessageBox = ({
.filter((file): file is File => !!file);

if (files.length) {
if(localStorage?.getItem('QA_BUG_PASTE_IMAGE_CLEARS_TEXT') === "1"){
chat.composer?.clear();
}
event.preventDefault();
onUploadFiles?.(files);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/server/modules/streamer/streamer.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ export abstract class Streamer<N extends keyof StreamerEvents> extends EventEmit
if (!subscriptions?.size) {
return false;
}

if (transform) {
void this.sendToManySubscriptions(subscriptions, origin, eventName, args, transform);

Expand Down
Loading