diff --git a/app/actions/actionsTypes.ts b/app/actions/actionsTypes.ts index 2273e3363..ae763c1d0 100644 --- a/app/actions/actionsTypes.ts +++ b/app/actions/actionsTypes.ts @@ -30,7 +30,9 @@ export const ROOM = createRequestTypes('ROOM', [ 'FORWARD', 'USER_TYPING', 'HISTORY_REQUEST', - 'HISTORY_FINISHED' + 'HISTORY_FINISHED', + 'FOCUSED_THREAD', + 'REMOVE_FOCUSED_THREAD' ]); export const INQUIRY = createRequestTypes('INQUIRY', [ ...defaultTypes, diff --git a/app/actions/room.ts b/app/actions/room.ts index 901aeba47..11d623eb8 100644 --- a/app/actions/room.ts +++ b/app/actions/room.ts @@ -54,6 +54,10 @@ export interface IRoomHistoryFinished extends Action { loaderId: string; } +export interface IFocusedThreadRoom extends Action { + tmid: string; +} + export type TActionsRoom = TSubscribeRoom & TUnsubscribeRoom & ILeaveRoom & @@ -61,7 +65,8 @@ export type TActionsRoom = TSubscribeRoom & IForwardRoom & IUserTyping & IRoomHistoryRequest & - IRoomHistoryFinished; + IRoomHistoryFinished & + IFocusedThreadRoom; export function subscribeRoom(rid: string): TSubscribeRoom { return { @@ -132,3 +137,16 @@ export function roomHistoryFinished({ loaderId }: { loaderId: string }): IRoomHi loaderId }; } + +export function focusedThreadRoom({ tmid }: { tmid: string }): IFocusedThreadRoom { + return { + type: ROOM.FOCUSED_THREAD, + tmid + }; +} + +export function removeFocusedThreadRoom(): Action { + return { + type: ROOM.REMOVE_FOCUSED_THREAD + }; +} diff --git a/app/lib/methods/subscriptions/room.ts b/app/lib/methods/subscriptions/room.ts index ea3960b00..61baf3b20 100644 --- a/app/lib/methods/subscriptions/room.ts +++ b/app/lib/methods/subscriptions/room.ts @@ -42,7 +42,6 @@ export default class RoomSubscription { private notifyRoomListener?: Promise; private messageReceivedListener?: Promise; private lastOpen?: Date; - private threadFocused?: string; constructor(rid: string) { this.rid = rid; @@ -312,8 +311,9 @@ export default class RoomSubscription { // Haptic Feedback when receiving message const { id: userId } = reduxStore.getState().login.user; + const { focusedThread } = reduxStore.getState().room; if ( - ((!message.tmid && !message.tlm && !this.threadFocused) || (message.tmid && message.tmid === this.threadFocused)) && + ((!message.tmid && !message.tlm && !focusedThread) || (message.tmid && message.tmid === focusedThread)) && message.u._id !== userId ) { const notificationInAppVibration = userPreferences.getBool(NOTIFICATION_IN_APP_VIBRATION); @@ -373,12 +373,4 @@ export default class RoomSubscription { const message = buildMessage(EJSON.fromJSONValue(ddpMessage.fields.args[0])) as IMessage; this.queue[message._id] = message; }; - - setThreadFocused = (tmid: string) => { - this.threadFocused = tmid; - }; - - removeThreadFocused = () => { - this.threadFocused = ''; - }; } diff --git a/app/reducers/room.test.ts b/app/reducers/room.test.ts index 8d9620e25..4d8ad8c24 100644 --- a/app/reducers/room.test.ts +++ b/app/reducers/room.test.ts @@ -1,7 +1,9 @@ import { deleteRoom, + focusedThreadRoom, forwardRoom, leaveRoom, + removeFocusedThreadRoom, removedRoom, roomHistoryFinished, roomHistoryRequest, @@ -69,4 +71,17 @@ describe('test room reducer', () => { const { historyLoaders } = mockedStore.getState().room; expect(historyLoaders).toEqual([]); }); + + it('should return focusedThread with the tmid properly', () => { + const tmid = 'focusedThread'; + mockedStore.dispatch(focusedThreadRoom({ tmid })); + const { focusedThread } = mockedStore.getState().room; + expect(focusedThread).toEqual(tmid); + }); + + it('should return focusedThread as empty after call removeFocusedThreadRoom', () => { + mockedStore.dispatch(removeFocusedThreadRoom()); + const { focusedThread } = mockedStore.getState().room; + expect(focusedThread).toEqual(''); + }); }); diff --git a/app/reducers/room.ts b/app/reducers/room.ts index c988d8683..857f9a8f4 100644 --- a/app/reducers/room.ts +++ b/app/reducers/room.ts @@ -8,13 +8,15 @@ export interface IRoom { isDeleting: boolean; subscribedRoom: string; historyLoaders: string[]; + focusedThread: string; } export const initialState: IRoom = { rid: '', isDeleting: false, subscribedRoom: '', - historyLoaders: [] + historyLoaders: [], + focusedThread: '' }; export default function (state = initialState, action: TActionsRoom): IRoom { @@ -68,6 +70,16 @@ export default function (state = initialState, action: TActionsRoom): IRoom { ...state, historyLoaders: state.historyLoaders.filter(loaderId => loaderId !== action.loaderId) }; + case ROOM.FOCUSED_THREAD: + return { + ...state, + focusedThread: action.tmid + }; + case ROOM.REMOVE_FOCUSED_THREAD: + return { + ...state, + focusedThread: '' + }; default: return state; } diff --git a/app/views/RoomView/index.tsx b/app/views/RoomView/index.tsx index 59c0b00ee..2d01248d8 100644 --- a/app/views/RoomView/index.tsx +++ b/app/views/RoomView/index.tsx @@ -95,6 +95,7 @@ import { goRoom, TGoRoomItem } from '../../lib/methods/helpers/goRoom'; import audioPlayer from '../../lib/methods/audioPlayer'; import { IListContainerRef, TListRef } from './List/definitions'; import { getThreadById } from '../../lib/database/services/Thread'; +import { focusedThreadRoom, removeFocusedThreadRoom } from '../../actions/room'; type TStateAttrsUpdate = keyof IRoomViewState; @@ -170,18 +171,18 @@ interface IRoomViewState { [key: string]: any; joined: boolean; room: - | TSubscriptionModel - | { - rid: string; - t: string; - name?: string; - fname?: string; - prid?: string; - joinCodeRequired?: boolean; - status?: string; - lastMessage?: ILastMessage; - sysMes?: boolean; - onHold?: boolean; + | TSubscriptionModel + | { + rid: string; + t: string; + name?: string; + fname?: string; + prid?: string; + joinCodeRequired?: boolean; + status?: string; + lastMessage?: ILastMessage; + sysMes?: boolean; + onHold?: boolean; }; roomUpdate: { [K in TRoomUpdate]?: any; @@ -230,7 +231,6 @@ class RoomView extends React.Component { }; private sub?: RoomClass; private unsubscribeBlur?: () => void; - private unsubscribeFocus?: () => void; constructor(props: IRoomViewProps) { super(props); @@ -308,7 +308,7 @@ class RoomView extends React.Component { } componentDidMount() { - const { navigation } = this.props; + const { navigation, dispatch } = this.props; this.mounted = true; this.didMountInteraction = InteractionManager.runAfterInteractions(() => { const { isAuthenticated } = this.props; @@ -339,11 +339,9 @@ class RoomView extends React.Component { this.unsubscribeBlur = navigation.addListener('blur', () => { audioPlayer.pauseCurrentAudio(); }); - this.unsubscribeFocus = navigation.addListener('focus', () => { - if (!this.tmid) { - this.sub?.removeThreadFocused(); - } - }); + if (this.tmid) { + dispatch(focusedThreadRoom({ tmid: this.tmid })); + } } shouldComponentUpdate(nextProps: IRoomViewProps, nextState: IRoomViewState) { @@ -414,6 +412,7 @@ class RoomView extends React.Component { }; async componentWillUnmount() { + const { dispatch } = this.props; const { editing, room } = this.state; const db = database.active; this.mounted = false; @@ -463,11 +462,11 @@ class RoomView extends React.Component { if (this.unsubscribeBlur) { this.unsubscribeBlur(); } - if (this.unsubscribeFocus) { - this.unsubscribeFocus(); - } EventEmitter.removeListener('connected', this.handleConnected); EventEmitter.removeListener('ROOM_REMOVED', this.handleRoomRemoved); + if (this.tmid) { + dispatch(removeFocusedThreadRoom()); + } if (!this.tmid) { // TODO: Refactor when audio becomes global await audioPlayer.unloadRoomAudios(this.rid); @@ -698,7 +697,7 @@ class RoomView extends React.Component { await RoomServices.getMessages({ rid: room.rid, t: room.t as RoomType, - ...('lastOpen' in room && room.lastOpen ? { lastOpen: room.lastOpen } : {}) + ...'lastOpen' in room && room.lastOpen ? { lastOpen: room.lastOpen } : {} }); // if room is joined @@ -1221,7 +1220,6 @@ class RoomView extends React.Component { sendLoadingEvent({ visible: false }); }, 300); } - this.sub?.setThreadFocused(item.tmid); return navigation.push('RoomView', { rid: this.rid, tmid: item.tmid, @@ -1233,7 +1231,6 @@ class RoomView extends React.Component { } if ('tlm' in item) { - this.sub?.setThreadFocused(item.id); return navigation.push('RoomView', { rid: this.rid, tmid: item.id, @@ -1512,7 +1509,7 @@ class RoomView extends React.Component { return ( <> (this.messageActions = ref)} + ref={ref => this.messageActions = ref} tmid={this.tmid} room={room} user={user} @@ -1523,7 +1520,7 @@ class RoomView extends React.Component { jumpToMessage={this.jumpToMessageByUrl} isReadOnly={readOnly} /> - (this.messageErrorActions = ref)} tmid={this.tmid} /> + this.messageErrorActions = ref} tmid={this.tmid} /> ); };