From 97807c245cb9fd7a45dd2258847019339f04fa8a Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Thu, 10 Aug 2023 10:48:11 +0700 Subject: [PATCH 01/19] Create is leaving client pusher event --- src/ONYXKEYS.js | 1 + src/libs/Pusher/EventType.js | 1 + src/libs/actions/Report.js | 101 +++++++++++++++++++++++++++++++++ src/pages/home/ReportScreen.js | 49 ++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 89e6aa9be419..75e22dbbf0d9 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -127,6 +127,7 @@ export default { REPORT_DRAFT_COMMENT_NUMBER_OF_LINES: 'reportDraftCommentNumberOfLines_', REPORT_IS_COMPOSER_FULL_SIZE: 'reportIsComposerFullSize_', REPORT_USER_IS_TYPING: 'reportUserIsTyping_', + REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_', SECURITY_GROUP: 'securityGroup_', TRANSACTION: 'transactions_', diff --git a/src/libs/Pusher/EventType.js b/src/libs/Pusher/EventType.js index 639e10020fc7..85ccc5e17242 100644 --- a/src/libs/Pusher/EventType.js +++ b/src/libs/Pusher/EventType.js @@ -5,6 +5,7 @@ export default { REPORT_COMMENT: 'reportComment', ONYX_API_UPDATE: 'onyxApiUpdate', + USER_IS_LEAVING_ROOM: 'client-userIsLeavingRoom', USER_IS_TYPING: 'client-userIsTyping', MULTIPLE_EVENTS: 'multipleEvents', MULTIPLE_EVENT_TYPE: { diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 2ac014e22a13..f241c3b5a657 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -79,6 +79,7 @@ Onyx.connect({ const allReports = {}; let conciergeChatReportID; const typingWatchTimers = {}; +const leavingWatchTimers = {}; /** * Get the private pusher channel name for a Report. @@ -111,6 +112,28 @@ function getNormalizedTypingStatus(typingStatus) { return normalizedTypingStatus; } +/** + * There are 2 possibilities that we can receive via pusher for a user's leaving status: + * 1. The "new" way from New Expensify is passed as {[login]: Boolean} (e.g. {yuwen@expensify.com: true}), where the value + * is whether the user with that login is leaving on the report or not. + * 2. The "old" way from e.com which is passed as {userLogin: login} (e.g. {userLogin: bstites@expensify.com}) + * + * This method makes sure that no matter which we get, we return the "new" format + * + * @param {Object} leavingStatus + * @returns {Object} + */ +function getNormalizedLeavingStatus(leavingStatus) { + let normalizedLeavingStatus = leavingStatus; + + if (_.first(_.keys(leavingStatus)) === 'userLogin') { + normalizedLeavingStatus = {[leavingStatus.userLogin]: true}; + } + + return normalizedLeavingStatus; +} + + /** * Initialize our pusher subscriptions to listen for someone typing in a report. * @@ -158,6 +181,53 @@ function subscribeToReportTypingEvents(reportID) { }); } +/** + * Initialize our pusher subscriptions to listen for someone typing in a report. + * + * @param {String} reportID + */ +function subscribeToReportLeavingEvents(reportID) { + if (!reportID) { + return; + } + + // Make sure we have a clean Leaving indicator before subscribing to leaving events + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, {}); + + const pusherChannelName = getReportChannelName(reportID); + Pusher.subscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM, (leavingStatus) => { + // If the pusher message comes from OldDot, we expect the leaving status to be keyed by user + // login OR by 'Concierge'. If the pusher message comes from NewDot, it is keyed by accountID + // since personal details are keyed by accountID. + const normalizedLeavingStatus = getNormalizedLeavingStatus(leavingStatus); + const accountIDOrLogin = _.first(_.keys(normalizedLeavingStatus)); + + if (!accountIDOrLogin) { + return; + } + + // Don't show the leaving indicator if the user is leaving on another platform + if (Number(accountIDOrLogin) === currentUserAccountID) { + return; + } + + // Use a combo of the reportID and the accountID or login as a key for holding our timers. + const reportUserIdentifier = `${reportID}-${accountIDOrLogin}`; + clearTimeout(leavingWatchTimers[reportUserIdentifier]); + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, normalizedLeavingStatus); + + // Wait for 1.5s of no additional leaving events before setting the status back to false. + leavingWatchTimers[reportUserIdentifier] = setTimeout(() => { + const leavingStoppedStatus = {}; + leavingStoppedStatus[accountIDOrLogin] = false; + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, leavingStoppedStatus); + delete leavingWatchTimers[reportUserIdentifier]; + }, 1500); + }).catch((error) => { + Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', false, {errorType: error.type, pusherChannelName}); + }); +} + /** * Remove our pusher subscriptions to listen for someone typing in a report. * @@ -173,6 +243,22 @@ function unsubscribeFromReportChannel(reportID) { Pusher.unsubscribe(pusherChannelName, Pusher.TYPE.USER_IS_TYPING); } +/** + * Remove our pusher subscriptions to listen for someone typing in a report. + * + * @param {String} reportID + */ +function unsubscribeFromLeavingRoomReportChannel(reportID) { + if (!reportID) { + return; + } + + const pusherChannelName = getReportChannelName(reportID); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, {}); + Pusher.unsubscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM); +} + + // New action subscriber array for report pages let newActionSubscribers = []; @@ -838,6 +924,17 @@ function broadcastUserIsTyping(reportID) { typingStatus[currentUserAccountID] = true; Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus); } +/** + * Broadcasts whether or not a user is typing on a report over the report's private pusher channel. + * + * @param {String} reportID + */ +function broadcastUserIsLeavingRoom(reportID) { + const privateReportChannelName = getReportChannelName(reportID); + const leavingStatus = {}; + leavingStatus[currentUserAccountID] = true; + Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM, leavingStatus); +} /** * When a report changes in Onyx, this fetches the report from the API if the report doesn't have a name @@ -1763,6 +1860,7 @@ function leaveRoom(reportID) { ], }, ); + broadcastUserIsLeavingRoom() navigateToConciergeChat(); } @@ -1878,10 +1976,13 @@ export { updateWriteCapabilityAndNavigate, updateNotificationPreferenceAndNavigate, subscribeToReportTypingEvents, + subscribeToReportLeavingEvents, unsubscribeFromReportChannel, + unsubscribeFromLeavingRoomReportChannel, saveReportComment, saveReportCommentNumberOfLines, broadcastUserIsTyping, + broadcastUserIsLeavingRoom, togglePinnedState, editReportComment, handleUserDeletedLinksInHtml, diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index c859bc6b8f05..c4d5a61bfbe7 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -83,6 +83,8 @@ const propTypes = { /** All of the personal details for everyone */ personalDetails: PropTypes.objectOf(personalDetailsPropType), + userLeavingStatuses: PropTypes.bool, + ...windowDimensionsPropTypes, ...viewportOffsetTopPropTypes, }; @@ -98,6 +100,7 @@ const defaultProps = { betas: [], policies: {}, accountManagerReportID: null, + userLeavingStatuses: false, personalDetails: {}, }; @@ -125,6 +128,7 @@ class ReportScreen extends React.Component { this.onSubmitComment = this.onSubmitComment.bind(this); this.chatWithAccountManager = this.chatWithAccountManager.bind(this); this.dismissBanner = this.dismissBanner.bind(this); + this.checkAndSubscribe = this.checkAndSubscribe.bind(this); this.state = { skeletonViewContainerHeight: reportActionsListViewHeight, @@ -135,6 +139,8 @@ class ReportScreen extends React.Component { this.flatListRef = React.createRef(); this.reactionListRef = React.createRef(); + + this.didSubscribeToReportLeavingEvents = React.createRef(); } componentDidMount() { @@ -152,14 +158,39 @@ class ReportScreen extends React.Component { this.fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); + this.checkAndSubscribe(); } componentDidUpdate(prevProps) { + + console.log('[debug] userLeavingStatuses', this.props.userLeavingStatuses) // If composer should be hidden, hide emoji picker as well if (ReportUtils.shouldHideComposer(this.props.report)) { EmojiPickerAction.hideEmojiPicker(true); } + // const onyxReportID = this.props.report.reportID; + // const prevOnyxReportID = prevProps.report.reportID; + // const routeReportID = getReportID(this.props.route); + + // // navigate to concierge when the room removed from another device (e.g. user leaving a room) + // // the report will not really null when removed, it will have defaultProps properties and values + // if ( + // prevOnyxReportID && + // prevOnyxReportID === routeReportID && + // !onyxReportID && + // // non-optimistic case + // (_.isEqual(this.props.report, defaultProps.report) || + // // optimistic case + // (prevProps.report.statusNum === CONST.REPORT.STATUS.OPEN && this.props.report.statusNum === CONST.REPORT.STATUS.CLOSED)) + // ) { + // // Navigation.goBack(); + // // Report.navigateToConciergeChat(); + // // // isReportRemoved will prevent showing when navigating + // // this.setState({isReportRemoved: true}); + // return; + // } + // If you already have a report open and are deeplinking to a new report on native, // the ReportScreen never actually unmounts and the reportID in the route also doesn't change. // Therefore, we need to compare if the existing reportID is the same as the one in the route @@ -172,9 +203,13 @@ class ReportScreen extends React.Component { this.fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); + this.checkAndSubscribe(); } componentWillUnmount() { + if(this.didSubscribeToReportLeavingEvents){ + Report.unsubscribeFromLeavingRoomReportChannel(this.props.report.reportID); + } if (!this.unsubscribeVisibilityListener) { return; } @@ -228,6 +263,17 @@ class ReportScreen extends React.Component { Navigation.navigate(ROUTES.getReportRoute(this.props.accountManagerReportID)); } + checkAndSubscribe() { + const { report, reportID } = this.props; + + const didCreateReportSuccessfully = !report.pendingFields || (!report.pendingFields.addWorkspaceRoom && !report.pendingFields.createChat); + + if (!this.didSubscribeToReportLeavingEvents.current && didCreateReportSuccessfully) { + Report.subscribeToReportLeavingEvents(reportID); + this.didSubscribeToReportLeavingEvents.current = true; + } + } + render() { const reportID = getReportID(this.props.route); const {addWorkspaceRoomOrChatPendingAction, addWorkspaceRoomOrChatErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(this.props.report); @@ -426,5 +472,8 @@ export default compose( personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, }, + userLeavingStatuses: { + key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, + }, }), )(ReportScreen); From b769dc838a9e04eac975955c1bd69704c70f5e22 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Thu, 10 Aug 2023 14:07:10 +0700 Subject: [PATCH 02/19] implement subscribeToReportLeavingEvents --- src/libs/Pusher/pusher.js | 13 +++++++ src/libs/actions/Report.js | 37 +++++++++++--------- src/pages/home/ReportScreen.js | 63 +++++++++++++++++----------------- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index 60587a68e173..5921d8448f51 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -195,8 +195,12 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) { */ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscribe = () => {}) { return new Promise((resolve, reject) => { + console.log('[debug] jiasjdawd', channelName) + // We cannot call subscribe() before init(). Prevent any attempt to do this on dev. if (!socket) { + console.log('[debug] ohjaihwa', channelName) + throw new Error(`[Pusher] instance not found. Pusher.subscribe() most likely has been called before Pusher.init()`); } @@ -205,11 +209,17 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri let channel = getChannel(channelName); if (!channel || !channel.subscribed) { + console.log('[debug] noahdwawwad', channelName) + channel = socket.subscribe(channelName); let isBound = false; channel.bind('pusher:subscription_succeeded', () => { + console.log('[debug] ahusyodiasd', channelName) + // Check so that we do not bind another event with each reconnect attempt if (!isBound) { + console.log('[debug] pjaisdh08q', channelName) + bindEventToChannel(channel, eventName, eventCallback); resolve(); isBound = true; @@ -224,6 +234,8 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri }); channel.bind('pusher:subscription_error', (data = {}) => { + console.log('[debug] jh98c20chc0asc', channelName) + const {type, error, status} = data; Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', { channelName, @@ -234,6 +246,7 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri reject(error); }); } else { + console.log('[debug] jouahsdiasd', channelName) bindEventToChannel(channel, eventName, eventCallback); resolve(); } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index f241c3b5a657..4cc5ed0eba50 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -187,42 +187,47 @@ function subscribeToReportTypingEvents(reportID) { * @param {String} reportID */ function subscribeToReportLeavingEvents(reportID) { + console.log('[debug] subscribeToReportLeavingEvents(reportID)', reportID) if (!reportID) { return; } // Make sure we have a clean Leaving indicator before subscribing to leaving events - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, {}); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, false); const pusherChannelName = getReportChannelName(reportID); Pusher.subscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM, (leavingStatus) => { + console.log('[debug] leavingStatus', leavingStatus) // If the pusher message comes from OldDot, we expect the leaving status to be keyed by user // login OR by 'Concierge'. If the pusher message comes from NewDot, it is keyed by accountID // since personal details are keyed by accountID. const normalizedLeavingStatus = getNormalizedLeavingStatus(leavingStatus); const accountIDOrLogin = _.first(_.keys(normalizedLeavingStatus)); + console.log('[debug] normalizedLeavingStatus', normalizedLeavingStatus) + console.log('[debug] accountIDOrLogin', accountIDOrLogin) if (!accountIDOrLogin) { return; } - // Don't show the leaving indicator if the user is leaving on another platform - if (Number(accountIDOrLogin) === currentUserAccountID) { + if (Number(accountIDOrLogin) !== currentUserAccountID) { return; } // Use a combo of the reportID and the accountID or login as a key for holding our timers. - const reportUserIdentifier = `${reportID}-${accountIDOrLogin}`; - clearTimeout(leavingWatchTimers[reportUserIdentifier]); - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, normalizedLeavingStatus); - - // Wait for 1.5s of no additional leaving events before setting the status back to false. - leavingWatchTimers[reportUserIdentifier] = setTimeout(() => { - const leavingStoppedStatus = {}; - leavingStoppedStatus[accountIDOrLogin] = false; - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, leavingStoppedStatus); - delete leavingWatchTimers[reportUserIdentifier]; - }, 1500); + // const reportUserIdentifier = `${reportID}-${accountIDOrLogin}`; + // clearTimeout(leavingWatchTimers[reportUserIdentifier]); + console.log('[debug] Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, true)'); + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, true); + // // Wait for 1.5s of no additional leaving events before setting the status back to false. + // leavingWatchTimers[reportUserIdentifier] = setTimeout(() => { + // const leavingStoppedStatus = {}; + // leavingStoppedStatus[accountIDOrLogin] = false; + // console.log('[debug] leavingStoppedStatus', leavingStoppedStatus) + + // Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, leavingStoppedStatus); + // delete leavingWatchTimers[reportUserIdentifier]; + // }, 1500); }).catch((error) => { Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', false, {errorType: error.type, pusherChannelName}); }); @@ -254,7 +259,7 @@ function unsubscribeFromLeavingRoomReportChannel(reportID) { } const pusherChannelName = getReportChannelName(reportID); - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, {}); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, false); Pusher.unsubscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM); } @@ -1860,7 +1865,7 @@ function leaveRoom(reportID) { ], }, ); - broadcastUserIsLeavingRoom() + broadcastUserIsLeavingRoom(reportID) navigateToConciergeChat(); } diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index c4d5a61bfbe7..e86df04d54f0 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -37,6 +37,7 @@ import * as ComposerActions from '../../libs/actions/Composer'; import ReportScreenContext from './ReportScreenContext'; import TaskHeaderActionButton from '../../components/TaskHeaderActionButton'; import DragAndDropProvider from '../../components/DragAndDrop/Provider'; +import CONST from '../../CONST'; const propTypes = { /** Navigation route context info provided by react navigation */ @@ -83,7 +84,7 @@ const propTypes = { /** All of the personal details for everyone */ personalDetails: PropTypes.objectOf(personalDetailsPropType), - userLeavingStatuses: PropTypes.bool, + userLeavingStatus: PropTypes.bool, ...windowDimensionsPropTypes, ...viewportOffsetTopPropTypes, @@ -100,7 +101,7 @@ const defaultProps = { betas: [], policies: {}, accountManagerReportID: null, - userLeavingStatuses: false, + userLeavingStatus: false, personalDetails: {}, }; @@ -163,40 +164,39 @@ class ReportScreen extends React.Component { componentDidUpdate(prevProps) { - console.log('[debug] userLeavingStatuses', this.props.userLeavingStatuses) // If composer should be hidden, hide emoji picker as well if (ReportUtils.shouldHideComposer(this.props.report)) { EmojiPickerAction.hideEmojiPicker(true); } - // const onyxReportID = this.props.report.reportID; - // const prevOnyxReportID = prevProps.report.reportID; - // const routeReportID = getReportID(this.props.route); - - // // navigate to concierge when the room removed from another device (e.g. user leaving a room) - // // the report will not really null when removed, it will have defaultProps properties and values - // if ( - // prevOnyxReportID && - // prevOnyxReportID === routeReportID && - // !onyxReportID && - // // non-optimistic case - // (_.isEqual(this.props.report, defaultProps.report) || - // // optimistic case - // (prevProps.report.statusNum === CONST.REPORT.STATUS.OPEN && this.props.report.statusNum === CONST.REPORT.STATUS.CLOSED)) - // ) { - // // Navigation.goBack(); - // // Report.navigateToConciergeChat(); - // // // isReportRemoved will prevent showing when navigating - // // this.setState({isReportRemoved: true}); - // return; - // } + const onyxReportID = this.props.report.reportID; + const prevOnyxReportID = prevProps.report.reportID; + const routeReportID = getReportID(this.props.route); + + console.log('[debug] userLeavingStatus', this.props.userLeavingStatus) + console.log('[debug] prevOnyxReportID', prevOnyxReportID) + console.log('[debug] routeReportID', routeReportID) + console.log('[debug] onyxReportID', onyxReportID) + + // navigate to concierge when the room removed from another device (e.g. user leaving a room) + if ( + // non-optimistic case + (!prevProps.userLeavingStatus && this.props.userLeavingStatus) || + // optimistic case + (prevOnyxReportID && + prevOnyxReportID === routeReportID && + !onyxReportID && + (prevProps.report.statusNum === CONST.REPORT.STATUS.OPEN && this.props.report.statusNum === CONST.REPORT.STATUS.CLOSED)) + ) { + Navigation.goBack(); + Report.navigateToConciergeChat(); + return; + } // If you already have a report open and are deeplinking to a new report on native, // the ReportScreen never actually unmounts and the reportID in the route also doesn't change. // Therefore, we need to compare if the existing reportID is the same as the one in the route // before deciding that we shouldn't call OpenReport. - const onyxReportID = this.props.report.reportID; - const routeReportID = getReportID(this.props.route); if (onyxReportID === prevProps.report.reportID && (!onyxReportID || onyxReportID === routeReportID)) { return; } @@ -264,12 +264,13 @@ class ReportScreen extends React.Component { } checkAndSubscribe() { - const { report, reportID } = this.props; + const {report} = this.props; const didCreateReportSuccessfully = !report.pendingFields || (!report.pendingFields.addWorkspaceRoom && !report.pendingFields.createChat); if (!this.didSubscribeToReportLeavingEvents.current && didCreateReportSuccessfully) { - Report.subscribeToReportLeavingEvents(reportID); + console.log('[debug] Report.subscribeToReportLeavingEvents(reportID);') + Report.subscribeToReportLeavingEvents(report.reportID); this.didSubscribeToReportLeavingEvents.current = true; } } @@ -340,7 +341,7 @@ class ReportScreen extends React.Component { shouldEnableKeyboardAvoidingView={isTopMostReportId} > `${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, + userLeavingStatus: { + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${getReportID(route)}`, }, }), )(ReportScreen); From c87ceb934bd0f4b2f5610ac137f1421ba3df7216 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Thu, 10 Aug 2023 14:29:09 +0700 Subject: [PATCH 03/19] Remove unnecessary code, run prettier --- src/libs/Pusher/pusher.js | 13 ------------- src/libs/actions/Report.js | 21 +-------------------- src/pages/home/ReportScreen.js | 14 +++----------- 3 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index 5921d8448f51..60587a68e173 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -195,12 +195,8 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) { */ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscribe = () => {}) { return new Promise((resolve, reject) => { - console.log('[debug] jiasjdawd', channelName) - // We cannot call subscribe() before init(). Prevent any attempt to do this on dev. if (!socket) { - console.log('[debug] ohjaihwa', channelName) - throw new Error(`[Pusher] instance not found. Pusher.subscribe() most likely has been called before Pusher.init()`); } @@ -209,17 +205,11 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri let channel = getChannel(channelName); if (!channel || !channel.subscribed) { - console.log('[debug] noahdwawwad', channelName) - channel = socket.subscribe(channelName); let isBound = false; channel.bind('pusher:subscription_succeeded', () => { - console.log('[debug] ahusyodiasd', channelName) - // Check so that we do not bind another event with each reconnect attempt if (!isBound) { - console.log('[debug] pjaisdh08q', channelName) - bindEventToChannel(channel, eventName, eventCallback); resolve(); isBound = true; @@ -234,8 +224,6 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri }); channel.bind('pusher:subscription_error', (data = {}) => { - console.log('[debug] jh98c20chc0asc', channelName) - const {type, error, status} = data; Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', { channelName, @@ -246,7 +234,6 @@ function subscribe(channelName, eventName, eventCallback = () => {}, onResubscri reject(error); }); } else { - console.log('[debug] jouahsdiasd', channelName) bindEventToChannel(channel, eventName, eventCallback); resolve(); } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 4cc5ed0eba50..a3a77667bf43 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -133,7 +133,6 @@ function getNormalizedLeavingStatus(leavingStatus) { return normalizedLeavingStatus; } - /** * Initialize our pusher subscriptions to listen for someone typing in a report. * @@ -187,7 +186,6 @@ function subscribeToReportTypingEvents(reportID) { * @param {String} reportID */ function subscribeToReportLeavingEvents(reportID) { - console.log('[debug] subscribeToReportLeavingEvents(reportID)', reportID) if (!reportID) { return; } @@ -197,14 +195,11 @@ function subscribeToReportLeavingEvents(reportID) { const pusherChannelName = getReportChannelName(reportID); Pusher.subscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM, (leavingStatus) => { - console.log('[debug] leavingStatus', leavingStatus) // If the pusher message comes from OldDot, we expect the leaving status to be keyed by user // login OR by 'Concierge'. If the pusher message comes from NewDot, it is keyed by accountID // since personal details are keyed by accountID. const normalizedLeavingStatus = getNormalizedLeavingStatus(leavingStatus); const accountIDOrLogin = _.first(_.keys(normalizedLeavingStatus)); - console.log('[debug] normalizedLeavingStatus', normalizedLeavingStatus) - console.log('[debug] accountIDOrLogin', accountIDOrLogin) if (!accountIDOrLogin) { return; @@ -214,20 +209,7 @@ function subscribeToReportLeavingEvents(reportID) { return; } - // Use a combo of the reportID and the accountID or login as a key for holding our timers. - // const reportUserIdentifier = `${reportID}-${accountIDOrLogin}`; - // clearTimeout(leavingWatchTimers[reportUserIdentifier]); - console.log('[debug] Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, true)'); Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, true); - // // Wait for 1.5s of no additional leaving events before setting the status back to false. - // leavingWatchTimers[reportUserIdentifier] = setTimeout(() => { - // const leavingStoppedStatus = {}; - // leavingStoppedStatus[accountIDOrLogin] = false; - // console.log('[debug] leavingStoppedStatus', leavingStoppedStatus) - - // Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM}${reportID}`, leavingStoppedStatus); - // delete leavingWatchTimers[reportUserIdentifier]; - // }, 1500); }).catch((error) => { Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', false, {errorType: error.type, pusherChannelName}); }); @@ -263,7 +245,6 @@ function unsubscribeFromLeavingRoomReportChannel(reportID) { Pusher.unsubscribe(pusherChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM); } - // New action subscriber array for report pages let newActionSubscribers = []; @@ -1865,7 +1846,7 @@ function leaveRoom(reportID) { ], }, ); - broadcastUserIsLeavingRoom(reportID) + broadcastUserIsLeavingRoom(reportID); navigateToConciergeChat(); } diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index e86df04d54f0..7d817af71524 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -163,7 +163,6 @@ class ReportScreen extends React.Component { } componentDidUpdate(prevProps) { - // If composer should be hidden, hide emoji picker as well if (ReportUtils.shouldHideComposer(this.props.report)) { EmojiPickerAction.hideEmojiPicker(true); @@ -173,11 +172,6 @@ class ReportScreen extends React.Component { const prevOnyxReportID = prevProps.report.reportID; const routeReportID = getReportID(this.props.route); - console.log('[debug] userLeavingStatus', this.props.userLeavingStatus) - console.log('[debug] prevOnyxReportID', prevOnyxReportID) - console.log('[debug] routeReportID', routeReportID) - console.log('[debug] onyxReportID', onyxReportID) - // navigate to concierge when the room removed from another device (e.g. user leaving a room) if ( // non-optimistic case @@ -186,7 +180,8 @@ class ReportScreen extends React.Component { (prevOnyxReportID && prevOnyxReportID === routeReportID && !onyxReportID && - (prevProps.report.statusNum === CONST.REPORT.STATUS.OPEN && this.props.report.statusNum === CONST.REPORT.STATUS.CLOSED)) + prevProps.report.statusNum === CONST.REPORT.STATUS.OPEN && + this.props.report.statusNum === CONST.REPORT.STATUS.CLOSED) ) { Navigation.goBack(); Report.navigateToConciergeChat(); @@ -207,7 +202,7 @@ class ReportScreen extends React.Component { } componentWillUnmount() { - if(this.didSubscribeToReportLeavingEvents){ + if (this.didSubscribeToReportLeavingEvents) { Report.unsubscribeFromLeavingRoomReportChannel(this.props.report.reportID); } if (!this.unsubscribeVisibilityListener) { @@ -265,11 +260,8 @@ class ReportScreen extends React.Component { checkAndSubscribe() { const {report} = this.props; - const didCreateReportSuccessfully = !report.pendingFields || (!report.pendingFields.addWorkspaceRoom && !report.pendingFields.createChat); - if (!this.didSubscribeToReportLeavingEvents.current && didCreateReportSuccessfully) { - console.log('[debug] Report.subscribeToReportLeavingEvents(reportID);') Report.subscribeToReportLeavingEvents(report.reportID); this.didSubscribeToReportLeavingEvents.current = true; } From b57b046624adb8dac585064e016af2956d41cfe3 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Thu, 10 Aug 2023 14:42:01 +0700 Subject: [PATCH 04/19] refine comment, remove leavingWatchTimers variable, refine checkAndSubscribe naming --- src/libs/actions/Report.js | 5 ++--- src/pages/home/ReportScreen.js | 9 +++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index a3a77667bf43..de1fe0eb4213 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -79,7 +79,6 @@ Onyx.connect({ const allReports = {}; let conciergeChatReportID; const typingWatchTimers = {}; -const leavingWatchTimers = {}; /** * Get the private pusher channel name for a Report. @@ -231,7 +230,7 @@ function unsubscribeFromReportChannel(reportID) { } /** - * Remove our pusher subscriptions to listen for someone typing in a report. + * Remove our pusher subscriptions to listen for someone leaving a report. * * @param {String} reportID */ @@ -911,7 +910,7 @@ function broadcastUserIsTyping(reportID) { Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus); } /** - * Broadcasts whether or not a user is typing on a report over the report's private pusher channel. + * Broadcasts whether or not a user is leaving on a report over the report's private pusher channel. * * @param {String} reportID */ diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 7d817af71524..dca4a74daf8a 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -84,6 +84,7 @@ const propTypes = { /** All of the personal details for everyone */ personalDetails: PropTypes.objectOf(personalDetailsPropType), + /** Whether user leaving current report that listen to another device leaveRoom trigger */ userLeavingStatus: PropTypes.bool, ...windowDimensionsPropTypes, @@ -129,7 +130,7 @@ class ReportScreen extends React.Component { this.onSubmitComment = this.onSubmitComment.bind(this); this.chatWithAccountManager = this.chatWithAccountManager.bind(this); this.dismissBanner = this.dismissBanner.bind(this); - this.checkAndSubscribe = this.checkAndSubscribe.bind(this); + this.checkAndSubscribeReportLeavingEvents = this.checkAndSubscribeReportLeavingEvents.bind(this); this.state = { skeletonViewContainerHeight: reportActionsListViewHeight, @@ -159,7 +160,7 @@ class ReportScreen extends React.Component { this.fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); - this.checkAndSubscribe(); + this.checkAndSubscribeReportLeavingEvents(); } componentDidUpdate(prevProps) { @@ -198,7 +199,7 @@ class ReportScreen extends React.Component { this.fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); - this.checkAndSubscribe(); + this.checkAndSubscribeReportLeavingEvents(); } componentWillUnmount() { @@ -258,7 +259,7 @@ class ReportScreen extends React.Component { Navigation.navigate(ROUTES.getReportRoute(this.props.accountManagerReportID)); } - checkAndSubscribe() { + checkAndSubscribeReportLeavingEvents() { const {report} = this.props; const didCreateReportSuccessfully = !report.pendingFields || (!report.pendingFields.addWorkspaceRoom && !report.pendingFields.createChat); if (!this.didSubscribeToReportLeavingEvents.current && didCreateReportSuccessfully) { From ea6c6fe36cc6138485c1ebb6b1297aba7b7b23db Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 23 Aug 2023 09:13:36 +0700 Subject: [PATCH 05/19] Move REPORT_USER_IS_LEAVING_ROOM to ONYXKEYS.ts --- src/ONYXKEYS.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 3c0b3ee9a6d6..686d2546bf59 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -233,6 +233,7 @@ const ONYXKEYS = { REPORT_DRAFT_COMMENT_NUMBER_OF_LINES: 'reportDraftCommentNumberOfLines_', REPORT_IS_COMPOSER_FULL_SIZE: 'reportIsComposerFullSize_', REPORT_USER_IS_TYPING: 'reportUserIsTyping_', + REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_', SECURITY_GROUP: 'securityGroup_', TRANSACTION: 'transactions_', @@ -361,6 +362,7 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES]: number; [ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE]: boolean; [ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: boolean; + [ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM]: boolean; [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; From e4d1363e973158876dc1c7c5d9c758ad8a5e6882 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Fri, 25 Aug 2023 14:35:39 +0700 Subject: [PATCH 06/19] Remove unnecessary code --- src/pages/home/ReportScreen.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 598d13ab9f58..d42886aeeb2b 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -163,10 +163,6 @@ class ReportScreen extends React.Component { } componentDidUpdate(prevProps) { - if (ReportUtils.shouldDisableWriteActions(this.props.report)) { - EmojiPickerAction.hideEmojiPicker(true); - } - const onyxReportID = this.props.report.reportID; const prevOnyxReportID = prevProps.report.reportID; const routeReportID = getReportID(this.props.route); From 96d1c4509e023f117974390bf10277cff7a0cfca Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 30 Aug 2023 06:24:53 +0700 Subject: [PATCH 07/19] Add prevReport.statusNum to dependency --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index ac96ed39bf4f..a1c280a498dd 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -308,7 +308,7 @@ function ReportScreen({ fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); - }, [route, report, errors, fetchReportIfNeeded, prevReport.reportID, userLeavingStatus]); + }, [route, report, errors, fetchReportIfNeeded, prevReport.reportID, userLeavingStatus, prevReport.statusNum]); useEffect(() => { // Ensures subscription event succeeds when the report/workspace room is created optimistically. From 9f47e6a2fcf95df8a4cb0fef16819483090f3f02 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 13 Sep 2023 11:14:39 +0700 Subject: [PATCH 08/19] Update src/libs/actions/Report.js Co-authored-by: Carlos Martins --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 2de649163079..cd3ca192d9a4 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -192,7 +192,7 @@ function subscribeToReportTypingEvents(reportID) { } /** - * Initialize our pusher subscriptions to listen for someone typing in a report. + * Initialize our pusher subscriptions to listen for someone leaving a room. * * @param {String} reportID */ From 6a1f0806474e48c60c4e05edc85ab3f8ef8a4823 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 13 Sep 2023 11:21:02 +0700 Subject: [PATCH 09/19] Update src/libs/actions/Report.js Co-authored-by: Carlos Martins --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index cd3ca192d9a4..65ec101aeb6d 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -937,7 +937,7 @@ function broadcastUserIsTyping(reportID) { Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus); } /** - * Broadcasts whether or not a user is leaving on a report over the report's private pusher channel. + * Broadcasts to the report's private pusher channel whether a user is leaving a report * * @param {String} reportID */ From 39c079b8d43ab38e0b3ae829f127957d15ebf7b0 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 13 Sep 2023 11:23:20 +0700 Subject: [PATCH 10/19] Update src/pages/home/ReportScreen.js Co-authored-by: Carlos Martins --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 74182d8db49a..0f824db5860c 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -88,7 +88,7 @@ const propTypes = { /** All of the personal details for everyone */ personalDetails: PropTypes.objectOf(personalDetailsPropType), - /** Whether user leaving current report that listen to another device leaveRoom trigger */ + /** Whether user is leaving the current report */ userLeavingStatus: PropTypes.bool, ...windowDimensionsPropTypes, From 70c6b304f3dd0edef9c9f606b876467a962298f2 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 13 Sep 2023 11:24:09 +0700 Subject: [PATCH 11/19] Update src/pages/home/ReportScreen.js Co-authored-by: Carlos Martins --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 0f824db5860c..ba4322d08393 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -290,7 +290,7 @@ function ReportScreen({ const prevOnyxReportID = prevReport.reportID; const routeReportID = getReportID(route); - // navigate to concierge when the room removed from another device (e.g. user leaving a room) + // Navigate to the Concierge chat if the room was removed from another device (e.g. user leaving a room) if ( // non-optimistic case userLeavingStatus || From f91b792e26b924ea6f37ab2e39d2131d2743ed7a Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 13 Sep 2023 11:28:49 +0700 Subject: [PATCH 12/19] make getNormalizedTypingStatus become generic getNormalizedStatus --- src/libs/actions/Report.js | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index cd3ca192d9a4..d61670aacc13 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -113,35 +113,14 @@ function getReportChannelName(reportID) { * @param {Object} typingStatus * @returns {Object} */ -function getNormalizedTypingStatus(typingStatus) { - let normalizedTypingStatus = typingStatus; +function getNormalizedStatus(status) { + let normalizedStatus = status; - if (_.first(_.keys(typingStatus)) === 'userLogin') { - normalizedTypingStatus = {[typingStatus.userLogin]: true}; + if (_.first(_.keys(status)) === 'userLogin') { + normalizedStatus = {[status.userLogin]: true}; } - return normalizedTypingStatus; -} - -/** - * There are 2 possibilities that we can receive via pusher for a user's leaving status: - * 1. The "new" way from New Expensify is passed as {[login]: Boolean} (e.g. {yuwen@expensify.com: true}), where the value - * is whether the user with that login is leaving on the report or not. - * 2. The "old" way from e.com which is passed as {userLogin: login} (e.g. {userLogin: bstites@expensify.com}) - * - * This method makes sure that no matter which we get, we return the "new" format - * - * @param {Object} leavingStatus - * @returns {Object} - */ -function getNormalizedLeavingStatus(leavingStatus) { - let normalizedLeavingStatus = leavingStatus; - - if (_.first(_.keys(leavingStatus)) === 'userLogin') { - normalizedLeavingStatus = {[leavingStatus.userLogin]: true}; - } - - return normalizedLeavingStatus; + return normalizedStatus; } /** @@ -162,7 +141,7 @@ function subscribeToReportTypingEvents(reportID) { // If the pusher message comes from OldDot, we expect the typing status to be keyed by user // login OR by 'Concierge'. If the pusher message comes from NewDot, it is keyed by accountID // since personal details are keyed by accountID. - const normalizedTypingStatus = getNormalizedTypingStatus(typingStatus); + const normalizedTypingStatus = getNormalizedStatus(typingStatus); const accountIDOrLogin = _.first(_.keys(normalizedTypingStatus)); if (!accountIDOrLogin) { @@ -209,7 +188,7 @@ function subscribeToReportLeavingEvents(reportID) { // If the pusher message comes from OldDot, we expect the leaving status to be keyed by user // login OR by 'Concierge'. If the pusher message comes from NewDot, it is keyed by accountID // since personal details are keyed by accountID. - const normalizedLeavingStatus = getNormalizedLeavingStatus(leavingStatus); + const normalizedLeavingStatus = getNormalizedStatus(leavingStatus); const accountIDOrLogin = _.first(_.keys(normalizedLeavingStatus)); if (!accountIDOrLogin) { From a658b186749b240e04a340fb59949e5cabdcfaaa Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 13 Sep 2023 11:39:12 +0700 Subject: [PATCH 13/19] fix lint --- src/libs/actions/Report.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index b74e532b1c39..f0ac66923002 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -103,14 +103,14 @@ function getReportChannelName(reportID) { } /** - * There are 2 possibilities that we can receive via pusher for a user's typing status: + * There are 2 possibilities that we can receive via pusher for a user's typing/leaving status: * 1. The "new" way from New Expensify is passed as {[login]: Boolean} (e.g. {yuwen@expensify.com: true}), where the value - * is whether the user with that login is typing on the report or not. + * is whether the user with that login is typing/leaving on the report or not. * 2. The "old" way from e.com which is passed as {userLogin: login} (e.g. {userLogin: bstites@expensify.com}) * * This method makes sure that no matter which we get, we return the "new" format * - * @param {Object} typingStatus + * @param {Object} status * @returns {Object} */ function getNormalizedStatus(status) { From 30c7499a5004cb5247ff16566cf7abce32beb258 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Fri, 15 Sep 2023 00:15:56 +0700 Subject: [PATCH 14/19] Ensure pusher's leavingStatus be sent earlier --- src/libs/actions/Report.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index f0ac66923002..92dbb0e5e0f6 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -1846,6 +1846,12 @@ function getCurrentUserAccountID() { function leaveRoom(reportID) { const report = lodashGet(allReports, [reportID], {}); const reportKeys = _.keys(report); + + // Pusher's leavingStatus should be sent earlier. + // Place the broadcast before calling the LeaveRoom API to prevent a race condition + // between Onyx report being null and Pusher's leavingStatus becoming true. + broadcastUserIsLeavingRoom(reportID); + API.write( 'LeaveRoom', { @@ -1887,7 +1893,6 @@ function leaveRoom(reportID) { if (Navigation.getTopmostReportId() === reportID) { Navigation.goBack(); } - broadcastUserIsLeavingRoom(reportID); navigateToConciergeChat(); } From b9a001eb84adf3a75be054f07d30889a4bc3910e Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Fri, 15 Sep 2023 00:44:57 +0700 Subject: [PATCH 15/19] Add prevUserLeavingStatus to the check --- src/pages/home/ReportScreen.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index ed29ccbb5954..b784c91b23db 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -146,6 +146,7 @@ function ReportScreen({ const flatListRef = useRef(); const reactionListRef = useRef(); const prevReport = usePrevious(report); + const prevUserLeavingStatus = usePrevious(userLeavingStatus); const [skeletonViewContainerHeight, setSkeletonViewContainerHeight] = useState(0); const [isBannerVisible, setIsBannerVisible] = useState(true); @@ -293,7 +294,7 @@ function ReportScreen({ // Navigate to the Concierge chat if the room was removed from another device (e.g. user leaving a room) if ( // non-optimistic case - userLeavingStatus || + (!prevUserLeavingStatus && userLeavingStatus) || // optimistic case (prevOnyxReportID && prevOnyxReportID === routeReportID && !onyxReportID && prevReport.statusNum === CONST.REPORT.STATUS.OPEN && report.statusNum === CONST.REPORT.STATUS.CLOSED) ) { @@ -312,7 +313,7 @@ function ReportScreen({ fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); - }, [route, report, errors, fetchReportIfNeeded, prevReport.reportID, userLeavingStatus, prevReport.statusNum]); + }, [route, report, errors, fetchReportIfNeeded, prevReport.reportID, prevUserLeavingStatus, userLeavingStatus, prevReport.statusNum]); useEffect(() => { // Ensures subscription event succeeds when the report/workspace room is created optimistically. From b3d2a0cc67d43ac6f35de668d4e1e4bf10fe27eb Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 20 Sep 2023 10:47:25 +0700 Subject: [PATCH 16/19] resolve leftover conflict --- src/pages/home/ReportScreen.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index a8438e0a4f09..794471864aa4 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -352,7 +352,7 @@ function ReportScreen({ // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowNotFoundPage = useMemo( - () => (!_.isEmpty(report) && !isDefaultReport && !report.reportID && !isOptimisticDelete && !report.isLoadingReportActions && !isLoading) || shouldHideReport, + () => (!_.isEmpty(report) && !isDefaultReport && !report.reportID && !isOptimisticDelete && !report.isLoadingReportActions && !isLoading && !userLeavingStatus) || shouldHideReport, [report, isLoading, shouldHideReport, isDefaultReport, isOptimisticDelete], ); @@ -368,11 +368,7 @@ function ReportScreen({ shouldEnableKeyboardAvoidingView={isTopMostReportId} > >>>>>> d0b49122d07ed51b974acce3981883e9b049a30c subtitleKey="notFound.noAccess" shouldShowCloseButton={false} shouldShowBackButton={isSmallScreenWidth} From 91c533e48386812078e37618530e08237a5be9aa Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 20 Sep 2023 10:48:06 +0700 Subject: [PATCH 17/19] resolve leftover conflict --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 794471864aa4..213f004ac416 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -353,7 +353,7 @@ function ReportScreen({ // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowNotFoundPage = useMemo( () => (!_.isEmpty(report) && !isDefaultReport && !report.reportID && !isOptimisticDelete && !report.isLoadingReportActions && !isLoading && !userLeavingStatus) || shouldHideReport, - [report, isLoading, shouldHideReport, isDefaultReport, isOptimisticDelete], + [report, isLoading, shouldHideReport, isDefaultReport, isOptimisticDelete, userLeavingStatus], ); return ( From 89263770bad930885e016f1ce3d1449d30174656 Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 20 Sep 2023 10:50:17 +0700 Subject: [PATCH 18/19] remove unnecessary code --- src/pages/home/ReportScreen.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 213f004ac416..6c11dcc01983 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -290,10 +290,6 @@ function ReportScreen({ fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); return () => { - if (!unsubscribeVisibilityListener) { - return; - } - unsubscribeVisibilityListener(); if (didSubscribeToReportLeavingEvents) { Report.unsubscribeFromLeavingRoomReportChannel(report.reportID); } From b2303b253db992b108842ae273f770592b2d2a7d Mon Sep 17 00:00:00 2001 From: Wildan Muhlis Date: Wed, 20 Sep 2023 10:55:54 +0700 Subject: [PATCH 19/19] change didSubscribeToReportLeavingEvents check to early return --- src/pages/home/ReportScreen.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 6c11dcc01983..8a9f50518dc8 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -290,9 +290,11 @@ function ReportScreen({ fetchReportIfNeeded(); ComposerActions.setShouldShowComposeInput(true); return () => { - if (didSubscribeToReportLeavingEvents) { - Report.unsubscribeFromLeavingRoomReportChannel(report.reportID); + if (!didSubscribeToReportLeavingEvents) { + return; } + + Report.unsubscribeFromLeavingRoomReportChannel(report.reportID); }; // I'm disabling the warning, as it expects to use exhaustive deps, even though we want this useEffect to run only on the first render.