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
10 changes: 8 additions & 2 deletions react/features/base/util/messageGrouping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface IMessageGroup<T extends IGroupableMessage> {
*
* @template T - The type of messages to group, must extend IGroupableMessage.
* @param {T[]} messages - The array of messages to group.
* @param {boolean} [disableReactionsInChat=false] - Whether to exclude reaction messages from the groups.
* @returns {IMessageGroup<T>[]} - An array of message groups, where each group contains messages from the same sender.
* @example
* const messages = [
Expand All @@ -53,8 +54,9 @@ export interface IMessageGroup<T extends IGroupableMessage> {
* // { senderId: "user2", messages: [{ participantId: "user2", timestamp: 3000 }] }
* // ]
*/
export function groupMessagesBySender<T extends IGroupableMessage>(
messages: T[]
export function groupMessagesBySender<T extends IGroupableMessage & { isReaction?: boolean; }>(
messages: T[],
disableReactionsInChat: boolean = false
): IMessageGroup<T>[] {
if (!messages?.length) {
return [];
Expand All @@ -64,6 +66,10 @@ export function groupMessagesBySender<T extends IGroupableMessage>(
let currentGroup: IMessageGroup<T> | null = null;

for (const message of messages) {
if (disableReactionsInChat && message.isReaction) {
continue;
}

if (!currentGroup || currentGroup.senderId !== message.participantId) {
currentGroup = {
messages: [ message ],
Expand Down
11 changes: 0 additions & 11 deletions react/features/chat/components/AbstractMessageContainer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component } from 'react';
import { ReactReduxContext } from 'react-redux';

import { IMessage } from '../types';

Expand All @@ -17,8 +16,6 @@ export interface IProps {
* @augments PureComponent
*/
export default class AbstractMessageContainer<P extends IProps, S> extends Component<P, S> {
static override contextType = ReactReduxContext;
declare context: React.ContextType<typeof ReactReduxContext>;

static defaultProps = {
messages: [] as IMessage[]
Expand All @@ -37,17 +34,9 @@ export default class AbstractMessageContainer<P extends IProps, S> extends Compo
let currentGrouping: IMessage[] = [];
let currentGroupParticipantId;

const { store } = this.context;
const state = store.getState();
const { disableReactionsInChat } = state['features/base/config'];

for (let i = 0; i < messagesCount; i++) {
const message = this.props.messages[i];

if (message.isReaction && disableReactionsInChat) {
continue;
}

if (message.participantId === currentGroupParticipantId) {
currentGrouping.push(message);
} else {
Expand Down
15 changes: 13 additions & 2 deletions react/features/chat/components/native/MessageContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { Component } from 'react';
import { FlatList, Text, TextStyle, View, ViewStyle } from 'react-native';
import { connect } from 'react-redux';
import { ReactReduxContext, connect } from 'react-redux';

import { translate } from '../../../base/i18n/functions';
import { IMessageGroup, groupMessagesBySender } from '../../../base/util/messageGrouping';
import { getDisableReactionsInChat } from '../../functions';
import { IMessage } from '../../types';

import ChatMessageGroup from './ChatMessageGroup';
Expand All @@ -18,6 +19,7 @@ interface IProps {
* Implements a container to render all the chat messages in a conference.
*/
class MessageContainer extends Component<IProps, any> {
static override contextType = ReactReduxContext;

static defaultProps = {
messages: [] as IMessage[]
Expand Down Expand Up @@ -110,7 +112,16 @@ class MessageContainer extends Component<IProps, any> {
* @returns {Array<Array<Object>>}
*/
_getMessagesGroupedBySender() {
return groupMessagesBySender(this.props.messages);
const store = this.context?.store;

if (!store) {
return groupMessagesBySender(this.props.messages, false);
}

const state = store.getState();
const disableReactionsInChat = getDisableReactionsInChat(state);

return groupMessagesBySender(this.props.messages, disableReactionsInChat);
}
}

Expand Down
15 changes: 14 additions & 1 deletion react/features/chat/components/web/MessageContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { throttle } from 'lodash-es';
import React, { Component, RefObject } from 'react';
import { ReactReduxContext } from 'react-redux';
import { scrollIntoView } from 'seamless-scroll-polyfill';

import { groupMessagesBySender } from '../../../base/util/messageGrouping';
import { MESSAGE_TYPE_LOCAL, MESSAGE_TYPE_REMOTE } from '../../constants';
import { getDisableReactionsInChat } from '../../functions';
import { IMessage } from '../../types';


Expand Down Expand Up @@ -38,6 +40,8 @@ interface IState {
* @augments Component
*/
export default class MessageContainer extends Component<IProps, IState> {
static override contextType = ReactReduxContext;

/**
* Component state used to decide when the hasNewMessages button to appear
* and where to scroll when click on hasNewMessages button.
Expand Down Expand Up @@ -332,6 +336,15 @@ export default class MessageContainer extends Component<IProps, IState> {
* @returns {Array<Array<Object>>}
*/
_getMessagesGroupedBySender() {
return groupMessagesBySender(this.props.messages);
const store = this.context?.store;

if (!store) {
return groupMessagesBySender(this.props.messages, false);
}

const state = store.getState();
const disableReactionsInChat = getDisableReactionsInChat(state);

return groupMessagesBySender(this.props.messages, disableReactionsInChat);
}
}
10 changes: 10 additions & 0 deletions react/features/chat/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,13 @@ export function isVisitorChatParticipant(
): participant is IVisitorChatParticipant {
return Boolean(participant && 'isVisitor' in participant && participant.isVisitor === true);
}

/**
* Selector for whether reactions are disabled in chat.
*
* @param {IReduxState} state - The redux state.
* @returns {boolean} True if reactions in chat are disabled.
*/
export function getDisableReactionsInChat(state: IReduxState): boolean {
return state['features/base/config']?.disableReactionsInChat === true;
}