[FIX] Messages not loading on some edge cases (#4801)
This commit is contained in:
parent
a1580811ed
commit
5387d31a68
|
@ -28,7 +28,9 @@ export const ROOM = createRequestTypes('ROOM', [
|
||||||
'DELETE',
|
'DELETE',
|
||||||
'REMOVED',
|
'REMOVED',
|
||||||
'FORWARD',
|
'FORWARD',
|
||||||
'USER_TYPING'
|
'USER_TYPING',
|
||||||
|
'HISTORY_REQUEST',
|
||||||
|
'HISTORY_FINISHED'
|
||||||
]);
|
]);
|
||||||
export const INQUIRY = createRequestTypes('INQUIRY', [
|
export const INQUIRY = createRequestTypes('INQUIRY', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Action } from 'redux';
|
import { Action } from 'redux';
|
||||||
|
|
||||||
import { ERoomType } from '../definitions/ERoomType';
|
import { ERoomType, RoomType } from '../definitions';
|
||||||
import { ROOM } from './actionsTypes';
|
import { ROOM } from './actionsTypes';
|
||||||
|
|
||||||
// TYPE RETURN RELATED
|
// TYPE RETURN RELATED
|
||||||
|
@ -44,7 +44,24 @@ interface IUserTyping extends Action {
|
||||||
status: boolean;
|
status: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TActionsRoom = TSubscribeRoom & TUnsubscribeRoom & ILeaveRoom & IDeleteRoom & IForwardRoom & IUserTyping;
|
export interface IRoomHistoryRequest extends Action {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
loaderId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoomHistoryFinished extends Action {
|
||||||
|
loaderId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionsRoom = TSubscribeRoom &
|
||||||
|
TUnsubscribeRoom &
|
||||||
|
ILeaveRoom &
|
||||||
|
IDeleteRoom &
|
||||||
|
IForwardRoom &
|
||||||
|
IUserTyping &
|
||||||
|
IRoomHistoryRequest &
|
||||||
|
IRoomHistoryFinished;
|
||||||
|
|
||||||
export function subscribeRoom(rid: string): TSubscribeRoom {
|
export function subscribeRoom(rid: string): TSubscribeRoom {
|
||||||
return {
|
return {
|
||||||
|
@ -99,3 +116,19 @@ export function userTyping(rid: string, status = true): IUserTyping {
|
||||||
status
|
status
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function roomHistoryRequest({ rid, t, loaderId }: { rid: string; t: RoomType; loaderId: string }): IRoomHistoryRequest {
|
||||||
|
return {
|
||||||
|
type: ROOM.HISTORY_REQUEST,
|
||||||
|
rid,
|
||||||
|
t,
|
||||||
|
loaderId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function roomHistoryFinished({ loaderId }: { loaderId: string }): IRoomHistoryFinished {
|
||||||
|
return {
|
||||||
|
type: ROOM.HISTORY_FINISHED,
|
||||||
|
loaderId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -407,7 +407,8 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
|
||||||
threadBadgeColor,
|
threadBadgeColor,
|
||||||
toggleFollowThread,
|
toggleFollowThread,
|
||||||
replies
|
replies
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{/* @ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<Message
|
<Message
|
||||||
id={id}
|
id={id}
|
||||||
|
|
|
@ -29,6 +29,7 @@ export * from './ISearch';
|
||||||
export * from './TUserStatus';
|
export * from './TUserStatus';
|
||||||
export * from './IProfile';
|
export * from './IProfile';
|
||||||
export * from './IReaction';
|
export * from './IReaction';
|
||||||
|
export * from './ERoomType';
|
||||||
|
|
||||||
export interface IBaseScreen<T extends Record<string, object | undefined>, S extends string> {
|
export interface IBaseScreen<T extends Record<string, object | undefined>, S extends string> {
|
||||||
navigation: StackNavigationProp<T, S>;
|
navigation: StackNavigationProp<T, S>;
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
import { SubscriptionType, TAnyMessageModel } from '../../../definitions';
|
import { SubscriptionType, TAnyMessageModel } from '../../definitions';
|
||||||
import { loadNextMessages, loadMessagesForRoom } from '../../../lib/methods';
|
import { loadNextMessages, loadMessagesForRoom } from '.';
|
||||||
import { MessageTypeLoad } from '../../../lib/constants';
|
import { MessageTypeLoad } from '../constants';
|
||||||
|
|
||||||
const getMoreMessages = ({
|
const getMoreMessages = ({
|
||||||
rid,
|
rid,
|
||||||
t,
|
t,
|
||||||
tmid,
|
|
||||||
loaderItem
|
loaderItem
|
||||||
}: {
|
}: {
|
||||||
rid: string;
|
rid: string;
|
||||||
t: SubscriptionType;
|
t: SubscriptionType;
|
||||||
tmid?: string;
|
|
||||||
loaderItem: TAnyMessageModel;
|
loaderItem: TAnyMessageModel;
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
|
if ([MessageTypeLoad.MORE, MessageTypeLoad.PREVIOUS_CHUNK].includes(loaderItem.t as MessageTypeLoad)) {
|
||||||
|
@ -25,7 +23,6 @@ const getMoreMessages = ({
|
||||||
if (loaderItem.t === MessageTypeLoad.NEXT_CHUNK) {
|
if (loaderItem.t === MessageTypeLoad.NEXT_CHUNK) {
|
||||||
return loadNextMessages({
|
return loadNextMessages({
|
||||||
rid,
|
rid,
|
||||||
tmid,
|
|
||||||
ts: loaderItem.ts as Date,
|
ts: loaderItem.ts as Date,
|
||||||
loaderItem
|
loaderItem
|
||||||
});
|
});
|
|
@ -16,6 +16,7 @@ export * from './getSingleMessage';
|
||||||
export * from './getSlashCommands';
|
export * from './getSlashCommands';
|
||||||
export * from './getThreadName';
|
export * from './getThreadName';
|
||||||
export * from './getUsersPresence';
|
export * from './getUsersPresence';
|
||||||
|
export * from './getMoreMessages';
|
||||||
export * from './loadMessagesForRoom';
|
export * from './loadMessagesForRoom';
|
||||||
export * from './loadMissedMessages';
|
export * from './loadMissedMessages';
|
||||||
export * from './loadNextMessages';
|
export * from './loadNextMessages';
|
||||||
|
|
|
@ -15,7 +15,6 @@ const COUNT = 50;
|
||||||
interface ILoadNextMessages {
|
interface ILoadNextMessages {
|
||||||
rid: string;
|
rid: string;
|
||||||
ts: Date;
|
ts: Date;
|
||||||
tmid?: string;
|
|
||||||
loaderItem: TMessageModel;
|
loaderItem: TMessageModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@ export function loadNextMessages(args: ILoadNextMessages): Promise<void> {
|
||||||
const loadMoreItem = {
|
const loadMoreItem = {
|
||||||
_id: generateLoadMoreId(lastMessage._id),
|
_id: generateLoadMoreId(lastMessage._id),
|
||||||
rid: lastMessage.rid,
|
rid: lastMessage.rid,
|
||||||
tmid: args.tmid,
|
|
||||||
ts: moment(lastMessage.ts).add(1, 'millisecond'),
|
ts: moment(lastMessage.ts).add(1, 'millisecond'),
|
||||||
t: MessageTypeLoad.NEXT_CHUNK
|
t: MessageTypeLoad.NEXT_CHUNK
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,9 +19,6 @@ export function loadSurroundingMessages({ messageId, rid }: { messageId: string;
|
||||||
let messages: IMessage[] = EJSON.fromJSONValue(data?.messages);
|
let messages: IMessage[] = EJSON.fromJSONValue(data?.messages);
|
||||||
messages = orderBy(messages, 'ts');
|
messages = orderBy(messages, 'ts');
|
||||||
|
|
||||||
const message = messages.find(m => m._id === messageId);
|
|
||||||
const tmid = message?.tmid;
|
|
||||||
|
|
||||||
if (messages?.length) {
|
if (messages?.length) {
|
||||||
if (data?.moreBefore) {
|
if (data?.moreBefore) {
|
||||||
const firstMessage = messages[0];
|
const firstMessage = messages[0];
|
||||||
|
@ -30,7 +27,6 @@ export function loadSurroundingMessages({ messageId, rid }: { messageId: string;
|
||||||
const loadMoreItem = {
|
const loadMoreItem = {
|
||||||
_id: generateLoadMoreId(firstMessage._id),
|
_id: generateLoadMoreId(firstMessage._id),
|
||||||
rid: firstMessage.rid,
|
rid: firstMessage.rid,
|
||||||
tmid,
|
|
||||||
ts: moment(firstMessage.ts).subtract(1, 'millisecond').toDate(),
|
ts: moment(firstMessage.ts).subtract(1, 'millisecond').toDate(),
|
||||||
t: MessageTypeLoad.PREVIOUS_CHUNK,
|
t: MessageTypeLoad.PREVIOUS_CHUNK,
|
||||||
msg: firstMessage.msg
|
msg: firstMessage.msg
|
||||||
|
@ -46,7 +42,6 @@ export function loadSurroundingMessages({ messageId, rid }: { messageId: string;
|
||||||
const loadMoreItem = {
|
const loadMoreItem = {
|
||||||
_id: generateLoadMoreId(lastMessage._id),
|
_id: generateLoadMoreId(lastMessage._id),
|
||||||
rid: lastMessage.rid,
|
rid: lastMessage.rid,
|
||||||
tmid,
|
|
||||||
ts: moment(lastMessage.ts).add(1, 'millisecond').toDate(),
|
ts: moment(lastMessage.ts).add(1, 'millisecond').toDate(),
|
||||||
t: MessageTypeLoad.NEXT_CHUNK,
|
t: MessageTypeLoad.NEXT_CHUNK,
|
||||||
msg: lastMessage.msg
|
msg: lastMessage.msg
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
import { deleteRoom, forwardRoom, leaveRoom, removedRoom, subscribeRoom, unsubscribeRoom } from '../actions/room';
|
import {
|
||||||
|
deleteRoom,
|
||||||
|
forwardRoom,
|
||||||
|
leaveRoom,
|
||||||
|
removedRoom,
|
||||||
|
roomHistoryFinished,
|
||||||
|
roomHistoryRequest,
|
||||||
|
subscribeRoom,
|
||||||
|
unsubscribeRoom
|
||||||
|
} from '../actions/room';
|
||||||
import { ERoomType } from '../definitions/ERoomType';
|
import { ERoomType } from '../definitions/ERoomType';
|
||||||
import { mockedStore } from './mockedStore';
|
import { mockedStore } from './mockedStore';
|
||||||
import { initialState } from './room';
|
import { initialState } from './room';
|
||||||
|
@ -48,4 +57,16 @@ describe('test room reducer', () => {
|
||||||
const { isDeleting } = mockedStore.getState().room;
|
const { isDeleting } = mockedStore.getState().room;
|
||||||
expect(isDeleting).toEqual(false);
|
expect(isDeleting).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return historyLoaders with one item after call historyRequest', () => {
|
||||||
|
mockedStore.dispatch(roomHistoryRequest({ rid: 'GENERAL', t: 'c', loaderId: 'loader' }));
|
||||||
|
const { historyLoaders } = mockedStore.getState().room;
|
||||||
|
expect(historyLoaders).toEqual(['loader']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return historyLoaders with empty array after call historyFinished', () => {
|
||||||
|
mockedStore.dispatch(roomHistoryFinished({ loaderId: 'loader' }));
|
||||||
|
const { historyLoaders } = mockedStore.getState().room;
|
||||||
|
expect(historyLoaders).toEqual([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,12 +7,14 @@ export interface IRoom {
|
||||||
rid: string;
|
rid: string;
|
||||||
isDeleting: boolean;
|
isDeleting: boolean;
|
||||||
subscribedRoom: string;
|
subscribedRoom: string;
|
||||||
|
historyLoaders: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialState: IRoom = {
|
export const initialState: IRoom = {
|
||||||
rid: '',
|
rid: '',
|
||||||
isDeleting: false,
|
isDeleting: false,
|
||||||
subscribedRoom: ''
|
subscribedRoom: '',
|
||||||
|
historyLoaders: []
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (state = initialState, action: TActionsRoom): IRoom {
|
export default function (state = initialState, action: TActionsRoom): IRoom {
|
||||||
|
@ -56,6 +58,16 @@ export default function (state = initialState, action: TActionsRoom): IRoom {
|
||||||
...state,
|
...state,
|
||||||
isDeleting: false
|
isDeleting: false
|
||||||
};
|
};
|
||||||
|
case ROOM.HISTORY_REQUEST:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
historyLoaders: [...state.historyLoaders, action.loaderId]
|
||||||
|
};
|
||||||
|
case ROOM.HISTORY_FINISHED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
historyLoaders: state.historyLoaders.filter(loaderId => loaderId !== action.loaderId)
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Alert } from 'react-native';
|
import { Alert } from 'react-native';
|
||||||
import { delay, put, race, select, take, takeLatest } from 'redux-saga/effects';
|
import { delay, put, race, select, take, takeLatest, actionChannel } from 'redux-saga/effects';
|
||||||
|
|
||||||
import EventEmitter from '../lib/methods/helpers/events';
|
import EventEmitter from '../lib/methods/helpers/events';
|
||||||
import Navigation from '../lib/navigation/appNavigation';
|
import Navigation from '../lib/navigation/appNavigation';
|
||||||
|
@ -10,6 +10,26 @@ import I18n from '../i18n';
|
||||||
import { showErrorAlert } from '../lib/methods/helpers/info';
|
import { showErrorAlert } from '../lib/methods/helpers/info';
|
||||||
import { LISTENER } from '../containers/Toast';
|
import { LISTENER } from '../containers/Toast';
|
||||||
import { Services } from '../lib/services';
|
import { Services } from '../lib/services';
|
||||||
|
import getMoreMessages from '../lib/methods/getMoreMessages';
|
||||||
|
import { getMessageById } from '../lib/database/services/Message';
|
||||||
|
|
||||||
|
function* watchHistoryRequests() {
|
||||||
|
const requestChan = yield actionChannel(types.ROOM.HISTORY_REQUEST);
|
||||||
|
while (true) {
|
||||||
|
const { rid, t, tmid, loaderId } = yield take(requestChan);
|
||||||
|
|
||||||
|
const loaderItem = yield getMessageById(loaderId);
|
||||||
|
if (loaderItem) {
|
||||||
|
try {
|
||||||
|
yield getMoreMessages({ rid, t, tmid, loaderItem });
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
} finally {
|
||||||
|
yield put({ type: types.ROOM.HISTORY_FINISHED, loaderId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const watchUserTyping = function* watchUserTyping({ rid, status }) {
|
const watchUserTyping = function* watchUserTyping({ rid, status }) {
|
||||||
const auth = yield select(state => state.login.isAuthenticated);
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
@ -132,5 +152,6 @@ const root = function* root() {
|
||||||
yield takeLatest(types.ROOM.LEAVE, handleLeaveRoom);
|
yield takeLatest(types.ROOM.LEAVE, handleLeaveRoom);
|
||||||
yield takeLatest(types.ROOM.DELETE, handleDeleteRoom);
|
yield takeLatest(types.ROOM.DELETE, handleDeleteRoom);
|
||||||
yield takeLatest(types.ROOM.FORWARD, handleForwardRoom);
|
yield takeLatest(types.ROOM.FORWARD, handleForwardRoom);
|
||||||
|
yield watchHistoryRequests();
|
||||||
};
|
};
|
||||||
export default root;
|
export default root;
|
||||||
|
|
|
@ -66,7 +66,7 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
|
||||||
*/
|
*/
|
||||||
.filter(sub => subscribedRoom !== sub.rid)
|
.filter(sub => subscribedRoom !== sub.rid)
|
||||||
.map(sub => sub.lastMessage && buildMessage(sub.lastMessage))
|
.map(sub => sub.lastMessage && buildMessage(sub.lastMessage))
|
||||||
.filter(lm => lm);
|
.filter(lm => lm && lm._id && lm.rid);
|
||||||
const lastMessagesIds = lastMessages.map(lm => lm._id).filter(lm => lm);
|
const lastMessagesIds = lastMessages.map(lm => lm._id).filter(lm => lm);
|
||||||
const existingMessages = yield messagesCollection.query(Q.where('id', Q.oneOf(lastMessagesIds))).fetch();
|
const existingMessages = yield messagesCollection.query(Q.where('id', Q.oneOf(lastMessagesIds))).fetch();
|
||||||
const messagesToUpdate = existingMessages.filter(i1 => lastMessages.find(i2 => i1.id === i2._id));
|
const messagesToUpdate = existingMessages.filter(i1 => lastMessages.find(i2 => i1.id === i2._id));
|
||||||
|
|
|
@ -11,28 +11,28 @@ export default {
|
||||||
title: 'RoomView/LoadMore'
|
title: 'RoomView/LoadMore'
|
||||||
};
|
};
|
||||||
|
|
||||||
const load = () => new Promise(res => setTimeout(res, 1000));
|
const LoadMore = ({ ...props }) => (
|
||||||
|
<LoadMoreComponent rid='rid' t='c' loaderId='loaderId' type={MessageTypeLoad.MORE} runOnRender={false} {...props} />
|
||||||
const LoadMore = ({ ...props }) => <LoadMoreComponent type={MessageTypeLoad.MORE} load={load} runOnRender={false} {...props} />;
|
);
|
||||||
|
|
||||||
export const Basic = () => (
|
export const Basic = () => (
|
||||||
<>
|
<>
|
||||||
<LoadMore />
|
<LoadMore loaderId='1' />
|
||||||
<LoadMore runOnRender />
|
<LoadMore loaderId='2' runOnRender />
|
||||||
<LoadMore type={MessageTypeLoad.PREVIOUS_CHUNK} />
|
<LoadMore loaderId='3' type={MessageTypeLoad.PREVIOUS_CHUNK} />
|
||||||
<LoadMore type={MessageTypeLoad.NEXT_CHUNK} />
|
<LoadMore loaderId='4' type={MessageTypeLoad.NEXT_CHUNK} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ThemeStory = ({ theme }: { theme: TSupportedThemes }) => (
|
const ThemeStory = ({ theme }: { theme: TSupportedThemes }) => (
|
||||||
<ThemeContext.Provider value={{ theme, colors: themes[theme] }}>
|
<ThemeContext.Provider value={{ theme, colors: themes[theme] }}>
|
||||||
<ScrollView style={{ backgroundColor: themes[theme].backgroundColor }}>
|
<ScrollView style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||||
<LoadMore type={MessageTypeLoad.PREVIOUS_CHUNK} />
|
<LoadMore loaderId='5' type={MessageTypeLoad.PREVIOUS_CHUNK} />
|
||||||
<Message msg='Hey!' theme={theme} />
|
<Message msg='Hey!' theme={theme} />
|
||||||
<Message msg={longText} theme={theme} isHeader={false} />
|
<Message msg={longText} theme={theme} isHeader={false} />
|
||||||
<Message msg='Older message' theme={theme} isHeader={false} />
|
<Message msg='Older message' theme={theme} isHeader={false} />
|
||||||
<LoadMore type={MessageTypeLoad.NEXT_CHUNK} />
|
<LoadMore loaderId='6' type={MessageTypeLoad.NEXT_CHUNK} />
|
||||||
<LoadMore type={MessageTypeLoad.MORE} />
|
<LoadMore loaderId='7' type={MessageTypeLoad.MORE} />
|
||||||
<Message msg={longText} theme={theme} />
|
<Message msg={longText} theme={theme} />
|
||||||
<Message msg='This is the third message' isHeader={false} theme={theme} />
|
<Message msg='This is the third message' isHeader={false} theme={theme} />
|
||||||
<Message msg='This is the second message' isHeader={false} theme={theme} />
|
<Message msg='This is the second message' isHeader={false} theme={theme} />
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { ActivityIndicator, StyleSheet, Text } from 'react-native';
|
import { ActivityIndicator, StyleSheet, Text } from 'react-native';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
import { MessageTypeLoad, themes } from '../../../lib/constants';
|
import { MessageTypeLoad } from '../../../lib/constants';
|
||||||
import { MessageType } from '../../../definitions';
|
import { MessageType, RoomType } from '../../../definitions';
|
||||||
import { useTheme } from '../../../theme';
|
import { useTheme } from '../../../theme';
|
||||||
import Touch from '../../../containers/Touch';
|
import Touch from '../../../containers/Touch';
|
||||||
import sharedStyles from '../../Styles';
|
import sharedStyles from '../../Styles';
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../../i18n';
|
||||||
|
import { roomHistoryRequest } from '../../../actions/room';
|
||||||
|
import { useAppSelector } from '../../../lib/hooks';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
button: {
|
button: {
|
||||||
|
@ -20,29 +23,25 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const LoadMore = ({
|
const LoadMore = React.memo(
|
||||||
load,
|
({
|
||||||
|
rid,
|
||||||
|
t,
|
||||||
|
loaderId,
|
||||||
type,
|
type,
|
||||||
runOnRender
|
runOnRender
|
||||||
}: {
|
}: {
|
||||||
load: Function;
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
loaderId: string;
|
||||||
type: MessageType;
|
type: MessageType;
|
||||||
runOnRender: boolean;
|
runOnRender: boolean;
|
||||||
}): React.ReactElement => {
|
}): React.ReactElement => {
|
||||||
const { theme } = useTheme();
|
const { colors } = useTheme();
|
||||||
const [loading, setLoading] = useState(false);
|
const dispatch = useDispatch();
|
||||||
|
const loading = useAppSelector(state => state.room.historyLoaders.some(historyLoader => historyLoader === loaderId));
|
||||||
|
|
||||||
const handleLoad = useCallback(async () => {
|
const handleLoad = () => dispatch(roomHistoryRequest({ rid, t, loaderId }));
|
||||||
try {
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setLoading(true);
|
|
||||||
await load();
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [loading]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (runOnRender) {
|
if (runOnRender) {
|
||||||
|
@ -61,12 +60,13 @@ const LoadMore = ({
|
||||||
return (
|
return (
|
||||||
<Touch onPress={handleLoad} style={styles.button} enabled={!loading}>
|
<Touch onPress={handleLoad} style={styles.button} enabled={!loading}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ActivityIndicator color={themes[theme].auxiliaryText} />
|
<ActivityIndicator color={colors.auxiliaryText} />
|
||||||
) : (
|
) : (
|
||||||
<Text style={[styles.text, { color: themes[theme].titleText }]}>{I18n.t(text)}</Text>
|
<Text style={[styles.text, { color: colors.titleText }]}>{I18n.t(text)}</Text>
|
||||||
)}
|
)}
|
||||||
</Touch>
|
</Touch>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default LoadMore;
|
export default LoadMore;
|
||||||
|
|
|
@ -75,7 +75,8 @@ import {
|
||||||
TThreadModel,
|
TThreadModel,
|
||||||
ICustomEmojis,
|
ICustomEmojis,
|
||||||
IEmoji,
|
IEmoji,
|
||||||
TGetCustomEmoji
|
TGetCustomEmoji,
|
||||||
|
RoomType
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, MESSAGE_TYPE_ANY_LOAD, MessageTypeLoad, themes } from '../../lib/constants';
|
import { E2E_MESSAGE_TYPE, E2E_STATUS, MESSAGE_TYPE_ANY_LOAD, MessageTypeLoad, themes } from '../../lib/constants';
|
||||||
import { TListRef } from './List/List';
|
import { TListRef } from './List/List';
|
||||||
|
@ -685,7 +686,11 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
await loadThreadMessages({ tmid: this.tmid, rid: this.rid });
|
await loadThreadMessages({ tmid: this.tmid, rid: this.rid });
|
||||||
} else {
|
} else {
|
||||||
const newLastOpen = new Date();
|
const newLastOpen = new Date();
|
||||||
await RoomServices.getMessages(room);
|
await RoomServices.getMessages({
|
||||||
|
rid: room.rid,
|
||||||
|
lastOpen: 'lastOpen' in room ? room.lastOpen : undefined,
|
||||||
|
t: room.t as RoomType
|
||||||
|
});
|
||||||
|
|
||||||
// if room is joined
|
// if room is joined
|
||||||
if (joined && 'id' in room) {
|
if (joined && 'id' in room) {
|
||||||
|
@ -1301,16 +1306,6 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
onLoadMoreMessages = (loaderItem: TAnyMessageModel) => {
|
|
||||||
const { room } = this.state;
|
|
||||||
return RoomServices.getMoreMessages({
|
|
||||||
rid: room.rid,
|
|
||||||
tmid: this.tmid,
|
|
||||||
t: room.t as any,
|
|
||||||
loaderItem
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
goToCannedResponses = () => {
|
goToCannedResponses = () => {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
Navigation.navigate('CannedResponsesListView', { rid: room.rid });
|
Navigation.navigate('CannedResponsesListView', { rid: room.rid });
|
||||||
|
@ -1337,7 +1332,9 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t as MessageTypeLoad)) {
|
if (item.t && MESSAGE_TYPE_ANY_LOAD.includes(item.t as MessageTypeLoad)) {
|
||||||
content = (
|
content = (
|
||||||
<LoadMore
|
<LoadMore
|
||||||
load={() => this.onLoadMoreMessages(item)}
|
rid={room.rid}
|
||||||
|
t={room.t as RoomType}
|
||||||
|
loaderId={item.id}
|
||||||
type={item.t}
|
type={item.t}
|
||||||
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
|
runOnRender={item.t === MessageTypeLoad.MORE && !previousItem}
|
||||||
/>
|
/>
|
||||||
|
@ -1502,7 +1499,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MessageActions
|
<MessageActions
|
||||||
ref={ref => this.messageActions = ref}
|
ref={ref => (this.messageActions = ref)}
|
||||||
tmid={this.tmid}
|
tmid={this.tmid}
|
||||||
room={room}
|
room={room}
|
||||||
user={user}
|
user={user}
|
||||||
|
@ -1512,7 +1509,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
||||||
onReactionPress={this.onReactionPress}
|
onReactionPress={this.onReactionPress}
|
||||||
isReadOnly={readOnly}
|
isReadOnly={readOnly}
|
||||||
/>
|
/>
|
||||||
<MessageErrorActions ref={ref => this.messageErrorActions = ref} tmid={this.tmid} />
|
<MessageErrorActions ref={ref => (this.messageErrorActions = ref)} tmid={this.tmid} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
import { loadMessagesForRoom, loadMissedMessages } from '../../../lib/methods';
|
import { loadMessagesForRoom, loadMissedMessages, RoomTypes } from '../../../lib/methods';
|
||||||
|
|
||||||
// TODO: clarify latest vs lastOpen
|
interface IBaseParams {
|
||||||
const getMessages = ({
|
|
||||||
rid,
|
|
||||||
t,
|
|
||||||
latest,
|
|
||||||
lastOpen,
|
|
||||||
loaderItem
|
|
||||||
}: {
|
|
||||||
rid: string;
|
rid: string;
|
||||||
t?: string;
|
|
||||||
latest?: Date;
|
|
||||||
lastOpen?: Date;
|
|
||||||
loaderItem?: any; // TODO: type this
|
|
||||||
}): Promise<void> => {
|
|
||||||
if (lastOpen) {
|
|
||||||
return loadMissedMessages({ rid, lastOpen });
|
|
||||||
}
|
}
|
||||||
return loadMessagesForRoom({ rid, t: t as any, latest, loaderItem });
|
|
||||||
|
interface ILoadMessagesForRoomParams extends IBaseParams {
|
||||||
|
t: RoomTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ILoadMissedMessagesParams extends IBaseParams {
|
||||||
|
lastOpen: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMessages = (params: ILoadMissedMessagesParams | ILoadMessagesForRoomParams): Promise<void> => {
|
||||||
|
if ('lastOpen' in params) {
|
||||||
|
return loadMissedMessages(params);
|
||||||
|
}
|
||||||
|
return loadMessagesForRoom(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getMessages;
|
export default getMessages;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import getMessages from './getMessages';
|
import getMessages from './getMessages';
|
||||||
import getMoreMessages from './getMoreMessages';
|
|
||||||
import getMessageInfo from './getMessageInfo';
|
import getMessageInfo from './getMessageInfo';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getMessages,
|
getMessages,
|
||||||
getMoreMessages,
|
|
||||||
getMessageInfo
|
getMessageInfo
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue