From 13a7b9686c7e9f82734ec255fea4e66bb44518d3 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 13 Dec 2022 13:56:53 -0700 Subject: [PATCH 01/13] Remove unnecessary method --- src/libs/Navigation/NavigationRoot.js | 1 - src/libs/UnreadIndicatorUpdater/index.js | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js index 2c8b4bf5f55a..47afe9e1433a 100644 --- a/src/libs/Navigation/NavigationRoot.js +++ b/src/libs/Navigation/NavigationRoot.js @@ -46,7 +46,6 @@ function parseAndLogRoute(state) { Log.info('Navigating to route', false, {path: currentPath}); } - UnreadIndicatorUpdater.throttledUpdatePageTitleAndUnreadCount(); Navigation.setIsNavigationReady(); } diff --git a/src/libs/UnreadIndicatorUpdater/index.js b/src/libs/UnreadIndicatorUpdater/index.js index 4cf82b19d376..3ed76ca581a9 100644 --- a/src/libs/UnreadIndicatorUpdater/index.js +++ b/src/libs/UnreadIndicatorUpdater/index.js @@ -1,21 +1,9 @@ import _ from 'underscore'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -import updateUnread from './updateUnread'; -import * as ReportUtils from '../ReportUtils'; const reports = {}; -/** - * Updates the title and favicon of the current browser tab and Mac OS or iOS dock icon with an unread indicator. - * Note: We are throttling this since listening for report changes can trigger many updates depending on how many reports - * a user has and how often they are updated. - */ -const throttledUpdatePageTitleAndUnreadCount = _.throttle(() => { - const totalCount = _.filter(reports, ReportUtils.isUnread).length; - updateUnread(totalCount); -}, 100, {leading: false}); - let connectionID; /** @@ -31,7 +19,6 @@ function listenForReportChanges() { } reports[report.reportID] = report; - throttledUpdatePageTitleAndUnreadCount(); }, }); } @@ -50,5 +37,4 @@ function stopListeningForReportChanges() { export default { listenForReportChanges, stopListeningForReportChanges, - throttledUpdatePageTitleAndUnreadCount, }; From 8083313416b51600eaebc8c28370ed23795c3ba0 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 13 Dec 2022 14:11:52 -0700 Subject: [PATCH 02/13] WIP on cleaning up unread report counter --- .../Navigation/AppNavigator/AuthScreens.js | 2 - src/libs/UnreadIndicatorUpdater/index.js | 48 +++++-------------- src/libs/actions/Session/index.js | 2 - src/libs/actions/SignInRedirect.js | 5 +- src/pages/signin/SignInPage.js | 4 -- 5 files changed, 17 insertions(+), 44 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 09aec059ff1d..577bc853e54d 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -101,8 +101,6 @@ class AuthScreens extends React.Component { User.subscribeToUserEvents(); }); - // Listen for report changes and fetch some data we need on initialization - UnreadIndicatorUpdater.listenForReportChanges(); App.openApp(); App.setUpPoliciesAndNavigate(this.props.session); Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); diff --git a/src/libs/UnreadIndicatorUpdater/index.js b/src/libs/UnreadIndicatorUpdater/index.js index 3ed76ca581a9..b1ac0d1d06df 100644 --- a/src/libs/UnreadIndicatorUpdater/index.js +++ b/src/libs/UnreadIndicatorUpdater/index.js @@ -1,40 +1,18 @@ import _ from 'underscore'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; +import updateUnread from './updateUnread/index'; +import * as ReportUtils from '../ReportUtils'; -const reports = {}; +let unreadReports = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (reportsFromOnyx) => { + console.log('!!!', reportsFromOnyx) + unreadReports = _.filter(reportsFromOnyx, ReportUtils.isUnread); + console.log('!!!', _.size(unreadReports)); -let connectionID; - -/** - * Bind to the report collection key and update - * the title and unread count indicators - */ -function listenForReportChanges() { - connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - callback: (report) => { - if (!report || !report.reportID) { - return; - } - - reports[report.reportID] = report; - }, - }); -} - -/** - * Remove the subscription callback when we no longer need it. - */ -function stopListeningForReportChanges() { - if (!connectionID) { - return; - } - - Onyx.disconnect(connectionID); -} - -export default { - listenForReportChanges, - stopListeningForReportChanges, -}; + updateUnread(_.size(unreadReports)); + }, +}); diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index ad10d0524aec..cfe2ee5433b5 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -369,8 +369,6 @@ function clearSignInData() { * Put any logic that needs to run when we are signed out here. This can be triggered when the current tab or another tab signs out. */ function cleanupSession() { - // We got signed out in this tab or another so clean up any subscriptions and timers - UnreadIndicatorUpdater.stopListeningForReportChanges(); PushNotification.deregister(); PushNotification.clearNotifications(); Pusher.disconnect(); diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index e66e50cab26c..40568ed0ca3c 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -5,6 +5,8 @@ import DateUtils from '../DateUtils'; import * as Localize from '../Localize'; import * as PersistedRequests from './PersistedRequests'; import NetworkConnection from '../NetworkConnection'; +import UnreadActionIndicator from '../../components/UnreadActionIndicator'; +import UnreadIndicatorUpdater from '../UnreadIndicatorUpdater'; let currentActiveClients; Onyx.connect({ @@ -62,7 +64,8 @@ function clearStorageAndRedirect(errorMessage) { if (errorMessage) { Onyx.merge(ONYXKEYS.SESSION, {errors: {[DateUtils.getMicroseconds()]: Localize.translateLocal(errorMessage)}}); } - }); + }) + // .finally(UnreadIndicatorUpdater.stopListeningForReportChanges); } /** diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js index 60788b07210c..659bc9357fd7 100644 --- a/src/pages/signin/SignInPage.js +++ b/src/pages/signin/SignInPage.js @@ -6,7 +6,6 @@ import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; import styles from '../../styles/styles'; -import updateUnread from '../../libs/UnreadIndicatorUpdater/updateUnread/index'; import compose from '../../libs/compose'; import SignInPageLayout from './SignInPageLayout'; import LoginForm from './LoginForm'; @@ -44,9 +43,6 @@ const defaultProps = { class SignInPage extends Component { componentDidMount() { - // Always reset the unread counter to zero on this page - // NOTE: We need to wait for the next tick to ensure that the unread indicator is updated - setTimeout(() => updateUnread(0), 0); Performance.measureTTI(); } From 38d81be8506ab3da83adea81f748ded02820580d Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 13:04:40 -0700 Subject: [PATCH 03/13] Update version of Onyx --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4930f9d4a28d..2252d38cc7e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,7 +69,7 @@ "react-native-image-picker": "^4.10.2", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.29", + "react-native-onyx": "1.0.31", "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", @@ -35456,9 +35456,9 @@ } }, "node_modules/react-native-onyx": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.29.tgz", - "integrity": "sha512-Zg7v6bimkRPqaAM5C/CqMswSObPGX+2BK2Gr7r4P1htSMjNlvn+fZ9gD4mwJBPgnoEUqMdFGLUshksHbE+GSMg==", + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.31.tgz", + "integrity": "sha512-WaX6dD6II7sZoiiNnifCh7X+V2AjwOtMx5mmrGYBuspPUpLOIj3Lt3GM66YRe5T9d5PmyoKUl0ULuYip/7uBTQ==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -69820,9 +69820,9 @@ } }, "react-native-onyx": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.29.tgz", - "integrity": "sha512-Zg7v6bimkRPqaAM5C/CqMswSObPGX+2BK2Gr7r4P1htSMjNlvn+fZ9gD4mwJBPgnoEUqMdFGLUshksHbE+GSMg==", + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.31.tgz", + "integrity": "sha512-WaX6dD6II7sZoiiNnifCh7X+V2AjwOtMx5mmrGYBuspPUpLOIj3Lt3GM66YRe5T9d5PmyoKUl0ULuYip/7uBTQ==", "requires": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", diff --git a/package.json b/package.json index 1f31b743b27b..ccc92236e2f8 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "react-native-image-picker": "^4.10.2", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.29", + "react-native-onyx": "1.0.31", "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", From 069c338d7b4b9c9c08c289210e2de53f749bbfe0 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 13:33:47 -0700 Subject: [PATCH 04/13] Update page title after JS is done running --- .../updateUnread/index.website.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libs/UnreadIndicatorUpdater/updateUnread/index.website.js b/src/libs/UnreadIndicatorUpdater/updateUnread/index.website.js index c39afe29551b..244eaf805d10 100644 --- a/src/libs/UnreadIndicatorUpdater/updateUnread/index.website.js +++ b/src/libs/UnreadIndicatorUpdater/updateUnread/index.website.js @@ -11,11 +11,15 @@ import CONFIG from '../../../CONFIG'; function updateUnread(totalCount) { const hasUnread = totalCount !== 0; - // There is a Chrome browser bug that causes the title to revert back to the previous when we are navigating back. Setting the title to an empty string - // seems to improve this issue. - document.title = ''; - document.title = hasUnread ? `(${totalCount}) ${CONFIG.SITE_TITLE}` : CONFIG.SITE_TITLE; - document.getElementById('favicon').href = hasUnread ? CONFIG.FAVICON.UNREAD : CONFIG.FAVICON.DEFAULT; + // This setTimeout is required because due to how react rendering messes with the DOM, the document title can't be modified synchronously, and we must wait until all JS is done + // running before setting the title. + setTimeout(() => { + // There is a Chrome browser bug that causes the title to revert back to the previous when we are navigating back. Setting the title to an empty string + // seems to improve this issue. + document.title = ''; + document.title = hasUnread ? `(${totalCount}) ${CONFIG.SITE_TITLE}` : CONFIG.SITE_TITLE; + document.getElementById('favicon').href = hasUnread ? CONFIG.FAVICON.UNREAD : CONFIG.FAVICON.DEFAULT; + }, 0); } export default updateUnread; From dedbdb23319b70f32da54c8016f7490ca45a1e4b Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 13:34:00 -0700 Subject: [PATCH 05/13] Update podfile lock too --- ios/Podfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c696014a9b31..b4226a18fb71 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -472,7 +472,7 @@ PODS: - React-Core - react-native-image-manipulator (1.0.5): - React - - react-native-image-picker (4.10.1): + - react-native-image-picker (4.10.2): - React-Core - react-native-netinfo (8.3.1): - React-Core @@ -980,7 +980,7 @@ SPEC CHECKSUMS: react-native-document-picker: f68191637788994baed5f57d12994aa32cf8bf88 react-native-flipper: dc5290261fbeeb2faec1bdc57ae6dd8d562e1de4 react-native-image-manipulator: c48f64221cfcd46e9eec53619c4c0374f3328a56 - react-native-image-picker: f2ab1215d17bcfe27b0eb6417cc236fd1f4775e7 + react-native-image-picker: bf34f3f516d139ed3e24c5f5a381a91819e349ea react-native-netinfo: 1a6035d3b9780221d407c277ebfb5722ace00658 react-native-pdf: 33c622cbdf776a649929e8b9d1ce2d313347c4fa react-native-plaid-link-sdk: 77052f329310ff5a36ddda276793f40d27c02bc4 From f23efa1118f52a953dc2b109875c33b3fd206a06 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 13:54:29 -0700 Subject: [PATCH 06/13] Remove some debug code --- src/libs/UnreadIndicatorUpdater/index.js | 6 +----- src/libs/actions/SignInRedirect.js | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libs/UnreadIndicatorUpdater/index.js b/src/libs/UnreadIndicatorUpdater/index.js index b1ac0d1d06df..09fa82612314 100644 --- a/src/libs/UnreadIndicatorUpdater/index.js +++ b/src/libs/UnreadIndicatorUpdater/index.js @@ -4,15 +4,11 @@ import ONYXKEYS from '../../ONYXKEYS'; import updateUnread from './updateUnread/index'; import * as ReportUtils from '../ReportUtils'; -let unreadReports = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT, waitForCollectionCallback: true, callback: (reportsFromOnyx) => { - console.log('!!!', reportsFromOnyx) - unreadReports = _.filter(reportsFromOnyx, ReportUtils.isUnread); - console.log('!!!', _.size(unreadReports)); - + const unreadReports = _.filter(reportsFromOnyx, ReportUtils.isUnread); updateUnread(_.size(unreadReports)); }, }); diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index 40568ed0ca3c..c415656d42b8 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -64,8 +64,7 @@ function clearStorageAndRedirect(errorMessage) { if (errorMessage) { Onyx.merge(ONYXKEYS.SESSION, {errors: {[DateUtils.getMicroseconds()]: Localize.translateLocal(errorMessage)}}); } - }) - // .finally(UnreadIndicatorUpdater.stopListeningForReportChanges); + }); } /** From d68cd5760a739ef25601d55483a00057fd583976 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 14:49:11 -0700 Subject: [PATCH 07/13] Remove unused imports --- src/libs/actions/SignInRedirect.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index c415656d42b8..e66e50cab26c 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -5,8 +5,6 @@ import DateUtils from '../DateUtils'; import * as Localize from '../Localize'; import * as PersistedRequests from './PersistedRequests'; import NetworkConnection from '../NetworkConnection'; -import UnreadActionIndicator from '../../components/UnreadActionIndicator'; -import UnreadIndicatorUpdater from '../UnreadIndicatorUpdater'; let currentActiveClients; Onyx.connect({ From 22a942b91e3fffe96da68d501a22e87247ec4a6a Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 14:49:56 -0700 Subject: [PATCH 08/13] Remove unused import --- src/libs/Navigation/AppNavigator/AuthScreens.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 577bc853e54d..1a6e8d0f5547 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -10,7 +10,6 @@ import compose from '../../compose'; import * as PersonalDetails from '../../actions/PersonalDetails'; import * as Pusher from '../../Pusher/pusher'; import PusherConnectionManager from '../../PusherConnectionManager'; -import UnreadIndicatorUpdater from '../../UnreadIndicatorUpdater'; import ROUTES from '../../../ROUTES'; import ONYXKEYS from '../../../ONYXKEYS'; import Timing from '../../actions/Timing'; From 1091618708794d5ebff5fb4a802b693c13ee0ec5 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 14:50:37 -0700 Subject: [PATCH 09/13] Remove unused import --- src/libs/actions/Session/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index cfe2ee5433b5..2092880d1efe 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -11,7 +11,6 @@ import PushNotification from '../../Notification/PushNotification'; import Timing from '../Timing'; import CONST from '../../../CONST'; import * as Localize from '../../Localize'; -import UnreadIndicatorUpdater from '../../UnreadIndicatorUpdater'; import Timers from '../../Timers'; import * as Pusher from '../../Pusher/pusher'; import * as User from '../User'; From e43d8af78d3648a2dfc9e401767bc6b22e4be8f8 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 14 Dec 2022 14:57:31 -0700 Subject: [PATCH 10/13] Remove unused import --- src/libs/Navigation/NavigationRoot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js index 47afe9e1433a..7dea3a743bf3 100644 --- a/src/libs/Navigation/NavigationRoot.js +++ b/src/libs/Navigation/NavigationRoot.js @@ -8,7 +8,6 @@ import AppNavigator from './AppNavigator'; import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator'; import themeColors from '../../styles/themes/default'; import styles from '../../styles/styles'; -import UnreadIndicatorUpdater from '../UnreadIndicatorUpdater'; import Log from '../Log'; // https://reactnavigation.org/docs/themes From 99f7c5730ab06f2f3700a2127b6e891714e55afc Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 15 Dec 2022 08:51:14 -0700 Subject: [PATCH 11/13] Import the lib for updating the unread count --- src/Expensify.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Expensify.js b/src/Expensify.js index 93224dfd9321..25ac4b22fdc8 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -24,6 +24,10 @@ import * as User from './libs/actions/User'; import NetworkConnection from './libs/NetworkConnection'; import Navigation from './libs/Navigation/Navigation'; +// This lib needs to be imported, but it has nothing to export since all it contains is an Onyx connection +// eslint-disable-next-line no-unused-vars +import UnreadIndicatorUpdater from './libs/UnreadIndicatorUpdater'; + Onyx.registerLogger(({level, message}) => { if (level === 'alert') { Log.alert(message); From dff42c68c8a4be22cfd37934d13b625a8bae70bf Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 15 Dec 2022 14:15:20 -0700 Subject: [PATCH 12/13] Fix failing tests --- tests/ui/UnreadIndicatorsTest.js | 2 +- tests/unit/NetworkTest.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/UnreadIndicatorsTest.js b/tests/ui/UnreadIndicatorsTest.js index cb777bcd61e2..9883c1bf04fc 100644 --- a/tests/ui/UnreadIndicatorsTest.js +++ b/tests/ui/UnreadIndicatorsTest.js @@ -184,7 +184,7 @@ function signInAndGetAppWithUnreadChat() { } describe('Unread Indicators', () => { - afterEach(Onyx.clear); + afterEach(() => Onyx.clear()); it('Display bold in the LHN for unread chat and new line indicator above the chat message when we navigate to it', () => { let renderedApp; diff --git a/tests/unit/NetworkTest.js b/tests/unit/NetworkTest.js index f0cb04f7cd5f..6b725d94626b 100644 --- a/tests/unit/NetworkTest.js +++ b/tests/unit/NetworkTest.js @@ -36,7 +36,7 @@ beforeEach(() => { // Wait for any Log command to finish and Onyx to fully clear jest.advanceTimersByTime(CONST.NETWORK.PROCESS_REQUEST_DELAY_MS); return waitForPromisesToResolve() - .then(Onyx.clear) + .then(() => Onyx.clear()) .then(waitForPromisesToResolve); }); From 4f7ea06769d7a49524f5ed548a4d5f7a3e354371 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 19 Dec 2022 10:47:17 -0700 Subject: [PATCH 13/13] Protect against null reports --- src/libs/ReportUtils.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index def6e0861156..aa6c677ab1f8 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1013,6 +1013,10 @@ function buildOptimisticWorkspaceChats(policyID, policyName) { * @returns {Boolean} */ function isUnread(report) { + if (!report) { + return false; + } + const lastReadSequenceNumber = report.lastReadSequenceNumber || 0; const maxSequenceNumber = report.maxSequenceNumber || 0; return lastReadSequenceNumber < maxSequenceNumber;