Chore: Migrate methods/loadSurroundingMessages to Typescript (#3733)

* Chore: Migrate methods/loadSurroundingMessages to Typescript

* tweaks

* tweak

* tweak

* tweaks to make ts happy

* instead as IMessage is optional u

* enum to MessageTypeLoad

* minor tweaks
This commit is contained in:
Reinaldo Neto 2022-03-03 17:25:03 -03:00 committed by GitHub
parent 16fd64b260
commit b06be5a2ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 78 deletions

View File

@ -1,5 +1,7 @@
export const MESSAGE_TYPE_LOAD_MORE = 'load_more';
export const MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK = 'load_previous_chunk';
export const MESSAGE_TYPE_LOAD_NEXT_CHUNK = 'load_next_chunk';
export enum MessageTypeLoad {
MORE = 'load_more',
PREVIOUS_CHUNK = 'load_previous_chunk',
NEXT_CHUNK = 'load_next_chunk'
}
export const MESSAGE_TYPE_ANY_LOAD = [MESSAGE_TYPE_LOAD_MORE, MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK, MESSAGE_TYPE_LOAD_NEXT_CHUNK];
export const MESSAGE_TYPE_ANY_LOAD = [MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK, MessageTypeLoad.NEXT_CHUNK];

View File

@ -926,8 +926,8 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
let msg = `[ ](${permalink}) `;
// if original message wasn't sent by current user and neither from a direct room
if (user.username !== replyingMessage.u.username && roomType !== 'd' && replyWithMention) {
msg += `@${replyingMessage.u.username} `;
if (user.username !== replyingMessage?.u?.username && roomType !== 'd' && replyWithMention) {
msg += `@${replyingMessage?.u?.username} `;
}
msg = `${msg} ${message}`;

View File

@ -1,27 +1,14 @@
import Model from '@nozbe/watermelondb/Model';
import { MarkdownAST } from '@rocket.chat/message-parser';
import { MessageTypeLoad } from '../constants/messageTypeLoad';
import { IAttachment } from './IAttachment';
import { IReaction } from './IReaction';
import {
MESSAGE_TYPE_LOAD_MORE,
MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK,
MESSAGE_TYPE_LOAD_NEXT_CHUNK
} from '../constants/messageTypeLoad';
import { TThreadMessageModel } from './IThreadMessage';
import { TThreadModel } from './IThread';
import { IUrlFromServer } from './IUrl';
export type MessageType =
| 'jitsi_call_started'
| 'discussion-created'
| 'e2e'
| 'load_more'
| 'rm'
| 'uj'
| typeof MESSAGE_TYPE_LOAD_MORE
| typeof MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK
| typeof MESSAGE_TYPE_LOAD_NEXT_CHUNK;
export type MessageType = 'jitsi_call_started' | 'discussion-created' | 'e2e' | 'load_more' | 'rm' | 'uj' | MessageTypeLoad;
export interface IUserMessage {
_id: string;

View File

@ -30,6 +30,8 @@ export enum ERoomTypes {
CHANNEL = 'channel'
}
type RelationModified<T extends Model> = { fetch(): Promise<T[]> } & Relation<T>;
export interface ISubscription {
_id: string; // _id belongs watermelonDB
id: string; // id from server
@ -93,10 +95,10 @@ export interface ISubscription {
teamMain?: boolean;
separator?: boolean;
// https://nozbe.github.io/WatermelonDB/Relation.html#relation-api
messages: Relation<TMessageModel>;
threads: Relation<TThreadModel>;
threadMessages: Relation<TThreadMessageModel>;
uploads: Relation<TUploadModel>;
messages: RelationModified<TMessageModel>;
threads: RelationModified<TThreadModel>;
threadMessages: RelationModified<TThreadMessageModel>;
uploads: RelationModified<TUploadModel>;
}
export type TSubscriptionModel = ISubscription & Model;

View File

@ -1,6 +1,7 @@
import moment from 'moment';
import { IMessage, MessageType, TMessageModel } from '../../definitions';
import { MessageTypeLoad } from '../../constants/messageTypeLoad';
import { IMessage, TMessageModel } from '../../definitions';
import log from '../../utils/log';
import { getMessageById } from '../database/services/Message';
import roomTypeToApiType, { RoomTypes } from '../rocketchat/methods/roomTypeToApiType';
@ -46,7 +47,7 @@ export default function loadMessagesForRoom(args: {
_id: generateLoadMoreId(lastMessage._id as string),
rid: lastMessage.rid,
ts: moment(lastMessage.ts).subtract(1, 'millisecond').toString(),
t: 'load_more' as MessageType,
t: MessageTypeLoad.MORE,
msg: lastMessage.msg
};
data.push(loadMoreMessage);

View File

@ -4,7 +4,7 @@ import orderBy from 'lodash/orderBy';
import log from '../../utils/log';
import { getMessageById } from '../database/services/Message';
import { MESSAGE_TYPE_LOAD_NEXT_CHUNK } from '../../constants/messageTypeLoad';
import { MessageTypeLoad } from '../../constants/messageTypeLoad';
import { generateLoadMoreId } from '../utils';
import updateMessages from './updateMessages';
import { TMessageModel } from '../../definitions';
@ -34,7 +34,7 @@ export default function loadNextMessages(args: ILoadNextMessages): Promise<void>
rid: lastMessage.rid,
tmid: args.tmid,
ts: moment(lastMessage.ts).add(1, 'millisecond'),
t: MESSAGE_TYPE_LOAD_NEXT_CHUNK
t: MessageTypeLoad.NEXT_CHUNK
};
messages.push(loadMoreItem);
}

View File

@ -4,21 +4,23 @@ import orderBy from 'lodash/orderBy';
import log from '../../utils/log';
import { getMessageById } from '../database/services/Message';
import { MESSAGE_TYPE_LOAD_NEXT_CHUNK, MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK } from '../../constants/messageTypeLoad';
import { MessageTypeLoad } from '../../constants/messageTypeLoad';
import sdk from '../rocketchat/services/sdk';
import { IMessage } from '../../definitions';
import { generateLoadMoreId } from '../utils';
import updateMessages from './updateMessages';
const COUNT = 50;
export default function loadSurroundingMessages({ messageId, rid }) {
export default function loadSurroundingMessages({ messageId, rid }: { messageId: string; rid: string }) {
return new Promise(async (resolve, reject) => {
try {
const data = await this.methodCallWrapper('loadSurroundingMessages', { _id: messageId, rid }, COUNT);
let messages = EJSON.fromJSONValue(data?.messages);
const data = await sdk.methodCallWrapper('loadSurroundingMessages', { _id: messageId, rid }, COUNT);
let messages: IMessage[] = EJSON.fromJSONValue(data?.messages);
messages = orderBy(messages, 'ts');
const message = messages.find(m => m._id === messageId);
const { tmid } = message;
const tmid = message?.tmid;
if (messages?.length) {
if (data?.moreBefore) {
@ -29,10 +31,10 @@ export default function loadSurroundingMessages({ messageId, rid }) {
_id: generateLoadMoreId(firstMessage._id),
rid: firstMessage.rid,
tmid,
ts: moment(firstMessage.ts).subtract(1, 'millisecond'),
t: MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK,
ts: moment(firstMessage.ts).subtract(1, 'millisecond').toDate(),
t: MessageTypeLoad.PREVIOUS_CHUNK,
msg: firstMessage.msg
};
} as IMessage;
messages.unshift(loadMoreItem);
}
}
@ -45,18 +47,18 @@ export default function loadSurroundingMessages({ messageId, rid }) {
_id: generateLoadMoreId(lastMessage._id),
rid: lastMessage.rid,
tmid,
ts: moment(lastMessage.ts).add(1, 'millisecond'),
t: MESSAGE_TYPE_LOAD_NEXT_CHUNK,
ts: moment(lastMessage.ts).add(1, 'millisecond').toDate(),
t: MessageTypeLoad.NEXT_CHUNK,
msg: lastMessage.msg
};
} as IMessage;
messages.push(loadMoreItem);
}
}
await updateMessages({ rid, update: messages });
return resolve(messages);
} else {
return resolve([]);
}
return resolve([]);
} catch (e) {
log(e);
reject(e);

View File

@ -7,11 +7,7 @@ import { longText } from '../../../../storybook/utils';
import { ThemeContext } from '../../../theme';
import { Message, MessageDecorator, StoryProvider } from '../../../../storybook/stories/Message';
import { themes } from '../../../constants/colors';
import {
MESSAGE_TYPE_LOAD_MORE,
MESSAGE_TYPE_LOAD_NEXT_CHUNK,
MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK
} from '../../../constants/messageTypeLoad';
import { MessageTypeLoad } from '../../../constants/messageTypeLoad';
import LoadMore from './index';
const stories = storiesOf('LoadMore', module);
@ -23,20 +19,20 @@ stories.add('basic', () => (
<>
<LoadMore load={load} />
<LoadMore load={load} runOnRender />
<LoadMore load={load} type={MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK} />
<LoadMore load={load} type={MESSAGE_TYPE_LOAD_NEXT_CHUNK} />
<LoadMore load={load} type={MessageTypeLoad.PREVIOUS_CHUNK} />
<LoadMore load={load} type={MessageTypeLoad.NEXT_CHUNK} />
</>
));
const ThemeStory = ({ theme }) => (
<ThemeContext.Provider value={{ theme }}>
<ScrollView style={{ backgroundColor: themes[theme].backgroundColor }}>
<LoadMore load={load} type={MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK} />
<LoadMore load={load} type={MessageTypeLoad.PREVIOUS_CHUNK} />
<Message msg='Hey!' theme={theme} />
<Message msg={longText} theme={theme} isHeader={false} />
<Message msg='Older message' theme={theme} isHeader={false} />
<LoadMore load={load} type={MESSAGE_TYPE_LOAD_NEXT_CHUNK} />
<LoadMore load={load} type={MESSAGE_TYPE_LOAD_MORE} />
<LoadMore load={load} type={MessageTypeLoad.NEXT_CHUNK} />
<LoadMore load={load} type={MessageTypeLoad.MORE} />
<Message msg={longText} theme={theme} />
<Message msg='This is the third message' isHeader={false} theme={theme} />
<Message msg='This is the second message' isHeader={false} theme={theme} />

View File

@ -2,7 +2,8 @@ import React, { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, StyleSheet, Text } from 'react-native';
import { themes } from '../../../constants/colors';
import { MESSAGE_TYPE_LOAD_NEXT_CHUNK, MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK } from '../../../constants/messageTypeLoad';
import { MessageTypeLoad } from '../../../constants/messageTypeLoad';
import { MessageType } from '../../../definitions';
import { useTheme } from '../../../theme';
import Touch from '../../../utils/touch';
import sharedStyles from '../../Styles';
@ -20,7 +21,15 @@ const styles = StyleSheet.create({
}
});
const LoadMore = ({ load, type, runOnRender }: { load: Function; type: string; runOnRender: boolean }): React.ReactElement => {
const LoadMore = ({
load,
type,
runOnRender
}: {
load: Function;
type: MessageType;
runOnRender: boolean;
}): React.ReactElement => {
const { theme } = useTheme();
const [loading, setLoading] = useState(false);
@ -43,10 +52,10 @@ const LoadMore = ({ load, type, runOnRender }: { load: Function; type: string; r
}, []);
let text = 'Load_More';
if (type === MESSAGE_TYPE_LOAD_NEXT_CHUNK) {
if (type === MessageTypeLoad.NEXT_CHUNK) {
text = 'Load_Newer';
}
if (type === MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK) {
if (type === MessageTypeLoad.PREVIOUS_CHUNK) {
text = 'Load_Older';
}

View File

@ -24,7 +24,7 @@ import I18n from '../../i18n';
import RoomHeader from '../../containers/RoomHeader';
import StatusBar from '../../containers/StatusBar';
import { themes } from '../../constants/colors';
import { MESSAGE_TYPE_ANY_LOAD, MESSAGE_TYPE_LOAD_MORE } from '../../constants/messageTypeLoad';
import { MESSAGE_TYPE_ANY_LOAD, MessageTypeLoad } from '../../constants/messageTypeLoad';
import debounce from '../../utils/debounce';
import ReactionsModal from '../../containers/ReactionsModal';
import { LISTENER } from '../../containers/Toast';
@ -851,7 +851,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
* if it's from server, we don't have it saved locally and so we fetch surroundings
* we test if it's not from threads because we're fetching from threads currently with `getThreadMessages`
*/
if (message.fromServer && !message.tmid) {
if (message.fromServer && !message.tmid && this.rid) {
await RocketChat.loadSurroundingMessages({ messageId, rid: this.rid });
}
// @ts-ignore
@ -1161,12 +1161,12 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
}
let content = null;
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t)) {
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t as MessageTypeLoad)) {
content = (
<LoadMore
load={() => this.onLoadMoreMessages(item)}
type={item.t}
runOnRender={item.t === MESSAGE_TYPE_LOAD_MORE && !previousItem}
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
/>
);
} else {

View File

@ -1,11 +1,7 @@
import { MessageType, SubscriptionType, TAnyMessageModel } from '../../../definitions';
import { SubscriptionType, TAnyMessageModel } from '../../../definitions';
import loadMessagesForRoom from '../../../lib/methods/loadMessagesForRoom';
import loadNextMessages from '../../../lib/methods/loadNextMessages';
import {
MESSAGE_TYPE_LOAD_MORE,
MESSAGE_TYPE_LOAD_NEXT_CHUNK,
MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK
} from '../../../constants/messageTypeLoad';
import { MessageTypeLoad } from '../../../constants/messageTypeLoad';
const getMoreMessages = ({
rid,
@ -18,7 +14,7 @@ const getMoreMessages = ({
tmid?: string;
loaderItem: TAnyMessageModel;
}): Promise<void> => {
if ([MESSAGE_TYPE_LOAD_MORE, MESSAGE_TYPE_LOAD_PREVIOUS_CHUNK].includes(loaderItem.t as MessageType)) {
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
return loadMessagesForRoom({
rid,
t: t as any,
@ -27,7 +23,7 @@ const getMoreMessages = ({
});
}
if (loaderItem.t === MESSAGE_TYPE_LOAD_NEXT_CHUNK) {
if (loaderItem.t === MessageTypeLoad.NEXT_CHUNK) {
return loadNextMessages({
rid,
tmid,

View File

@ -7,7 +7,6 @@ import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
import { HeaderBackButton, StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
import { RouteProp } from '@react-navigation/native';
import { Observable, Subscription } from 'rxjs';
import Database from '@nozbe/watermelondb/Database';
import ActivityIndicator from '../../containers/ActivityIndicator';
import I18n from '../../i18n';
@ -33,13 +32,12 @@ import EventEmitter from '../../utils/events';
import { LISTENER } from '../../containers/Toast';
import SearchHeader from '../../containers/SearchHeader';
import { ChatsStackParamList } from '../../stacks/types';
import { IThreadResult, TThreadModel } from '../../definitions/IThread';
import { Filter } from './filters';
import DropdownItemHeader from './Dropdown/DropdownItemHeader';
import Dropdown from './Dropdown';
import Item from './Item';
import styles from './styles';
import { SubscriptionType, TSubscriptionModel } from '../../definitions/ISubscription';
import { IMessage, SubscriptionType, TSubscriptionModel, TThreadModel } from '../../definitions';
const API_FETCH_COUNT = 50;
@ -259,8 +257,8 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
remove,
lastThreadSync
}: {
update: IThreadResult[];
remove?: IThreadResult[];
update: IMessage[];
remove?: IMessage[];
lastThreadSync: Date;
}) => {
const { subscription } = this.state;
@ -272,11 +270,9 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
}
try {
const db: Database = database.active;
const db = database.active;
const threadsCollection = db.get('threads');
// TODO: Refactor when migrate room
// @ts-ignore
const allThreadsRecords = (await subscription.threads.fetch()) as TThreadModel[];
const allThreadsRecords = await subscription.threads.fetch();
let threadsToCreate: any[] = [];
let threadsToUpdate: any[] = [];
let threadsToDelete: any[] = [];
@ -287,7 +283,7 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
}
if (update && update.length) {
update = update.map(m => buildMessage(m)) as IThreadResult[];
update = update.map(m => buildMessage(m)) as IMessage[];
// filter threads
threadsToCreate = update.filter(i1 => !allThreadsRecords.find((i2: { id: string }) => i1._id === i2.id));
threadsToUpdate = allThreadsRecords.filter((i1: { id: string }) => update.find(i2 => i1.id === i2._id));