diff --git a/src/CONST.ts b/src/CONST.ts
index 3d69c83c5c22..283195562e49 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -483,6 +483,7 @@ const CONST = {
MAX_REPORT_PREVIEW_RECEIPTS: 3,
},
REPORT: {
+ MAX_COUNT_BEFORE_FOCUS_UPDATE: 30,
MAXIMUM_PARTICIPANTS: 8,
SPLIT_REPORTID: '-2',
ACTIONS: {
diff --git a/src/Expensify.js b/src/Expensify.js
index 1b692f86a197..aece93c0ff4d 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -7,6 +7,7 @@ import _ from 'underscore';
import ConfirmModal from './components/ConfirmModal';
import DeeplinkWrapper from './components/DeeplinkWrapper';
import EmojiPicker from './components/EmojiPicker/EmojiPicker';
+import FocusModeNotification from './components/FocusModeNotification';
import GrowlNotification from './components/GrowlNotification';
import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper';
import SplashScreenHider from './components/SplashScreenHider';
@@ -76,6 +77,9 @@ const propTypes = {
/** Whether the app is waiting for the server's response to determine if a room is public */
isCheckingPublicRoom: PropTypes.bool,
+ /** Whether we should display the notification alerting the user that focus mode has been auto-enabled */
+ focusModeNotification: PropTypes.bool,
+
...withLocalizePropTypes,
};
@@ -88,6 +92,7 @@ const defaultProps = {
isSidebarLoaded: false,
screenShareRequest: null,
isCheckingPublicRoom: true,
+ focusModeNotification: false,
};
const SplashScreenHiddenContext = React.createContext({});
@@ -221,6 +226,7 @@ function Expensify(props) {
isVisible
/>
) : null}
+ {props.focusModeNotification ? : null}
>
)}
@@ -261,6 +267,10 @@ export default compose(
screenShareRequest: {
key: ONYXKEYS.SCREEN_SHARE_REQUEST,
},
+ focusModeNotification: {
+ key: ONYXKEYS.FOCUS_MODE_NOTIFICATION,
+ initWithStoredValues: false,
+ },
}),
)(Expensify);
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index a983ec5acba5..97f24a2710aa 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -152,6 +152,12 @@ const ONYXKEYS = {
/** The user's cash card and imported cards (including the Expensify Card) */
CARD_LIST: 'cardList',
+ /** Whether the user has tried focus mode yet */
+ NVP_TRY_FOCUS_MODE: 'tryFocusMode',
+
+ /** Boolean flag used to display the focus mode notification */
+ FOCUS_MODE_NOTIFICATION: 'focusModeNotification',
+
/** Stores information about the user's saved statements */
WALLET_STATEMENT: 'walletStatement',
@@ -383,6 +389,8 @@ type OnyxValues = {
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf;
[ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
[ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string;
+ [ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean;
+ [ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean;
[ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: Record;
[ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[];
[ONYXKEYS.PUSH_NOTIFICATIONS_ENABLED]: boolean;
diff --git a/src/components/FocusModeNotification.js b/src/components/FocusModeNotification.js
new file mode 100644
index 000000000000..37d8e4848b98
--- /dev/null
+++ b/src/components/FocusModeNotification.js
@@ -0,0 +1,47 @@
+import React, {useEffect} from 'react';
+import useEnvironment from '@hooks/useEnvironment';
+import useLocalize from '@hooks/useLocalize';
+import styles from '@styles/styles';
+import * as Link from '@userActions/Link';
+import * as User from '@userActions/User';
+import CONST from '@src/CONST';
+import ConfirmModal from './ConfirmModal';
+import Text from './Text';
+import TextLinkWithRef from './TextLink';
+
+function FocusModeNotification() {
+ const {environmentURL} = useEnvironment();
+ const {translate} = useLocalize();
+ useEffect(() => {
+ User.updateChatPriorityMode(CONST.PRIORITY_MODE.GSD, true);
+ }, []);
+ const href = `${environmentURL}/settings/preferences/priority-mode`;
+ return (
+
+ {translate('focusModeUpdateModal.prompt')}
+ {
+ User.clearFocusModeNotification();
+ Link.openLink(href, environmentURL);
+ }}
+ >
+ {translate('common.here')}
+
+ .
+
+ }
+ isVisible
+ />
+ );
+}
+
+FocusModeNotification.displayName = 'FocusModeNotification';
+export default FocusModeNotification;
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
index 63973ea43e19..8f1406439be9 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
@@ -6,15 +6,10 @@ import AnchorForCommentsOnly from '@components/AnchorForCommentsOnly';
import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils';
import Text from '@components/Text';
import useEnvironment from '@hooks/useEnvironment';
-import Navigation from '@libs/Navigation/Navigation';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
-import * as Url from '@libs/Url';
import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
-import * as Session from '@userActions/Session';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
import htmlRendererPropTypes from './htmlRendererPropTypes';
function AnchorRenderer(props) {
@@ -26,50 +21,8 @@ function AnchorRenderer(props) {
const displayName = lodashGet(props.tnode, 'domNode.children[0].data', '');
const parentStyle = lodashGet(props.tnode, 'parent.styles.nativeTextRet', {});
const attrHref = htmlAttribs.href || '';
- const attrPath = Url.getPathFromURL(attrHref);
- const hasSameOrigin = Url.hasSameExpensifyOrigin(attrHref, environmentURL);
- const hasExpensifyOrigin = Url.hasSameExpensifyOrigin(attrHref, CONFIG.EXPENSIFY.EXPENSIFY_URL) || Url.hasSameExpensifyOrigin(attrHref, CONFIG.EXPENSIFY.STAGING_API_ROOT);
- const internalNewExpensifyPath =
- (Url.hasSameExpensifyOrigin(attrHref, CONST.NEW_EXPENSIFY_URL) ||
- Url.hasSameExpensifyOrigin(attrHref, CONST.STAGING_NEW_EXPENSIFY_URL) ||
- attrHref.startsWith(CONST.DEV_NEW_EXPENSIFY_URL)) &&
- !CONST.PATHS_TO_TREAT_AS_EXTERNAL.includes(attrPath)
- ? attrPath
- : '';
- const internalExpensifyPath =
- hasExpensifyOrigin && !attrPath.startsWith(CONFIG.EXPENSIFY.CONCIERGE_URL_PATHNAME) && !attrPath.startsWith(CONFIG.EXPENSIFY.DEVPORTAL_URL_PATHNAME) && attrPath;
- const navigateToLink = () => {
- // There can be messages from Concierge with links to specific NewDot reports. Those URLs look like this:
- // https://www.expensify.com.dev/newdotreport?reportID=3429600449838908 and they have a target="_blank" attribute. This is so that when a user is on OldDot,
- // clicking on the link will open the chat in NewDot. However, when a user is in NewDot and clicks on the concierge link, the link needs to be handled differently.
- // Normally, the link would be sent to Link.openOldDotLink() and opened in a new tab, and that's jarring to the user. Since the intention is to link to a specific NewDot chat,
- // the reportID is extracted from the URL and then opened as an internal link, taking the user straight to the chat in the same tab.
- if (hasExpensifyOrigin && attrHref.indexOf('newdotreport?reportID=') > -1) {
- const reportID = attrHref.split('newdotreport?reportID=').pop();
- const reportRoute = ROUTES.REPORT_WITH_ID.getRoute(reportID);
- Navigation.navigate(reportRoute);
- return;
- }
-
- // If we are handling a New Expensify link then we will assume this should be opened by the app internally. This ensures that the links are opened internally via react-navigation
- // instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag)
- if (internalNewExpensifyPath && hasSameOrigin) {
- if (Session.isAnonymousUser() && !Session.canAccessRouteByAnonymousUser(internalNewExpensifyPath)) {
- Session.signOutAndRedirectToSignIn();
- return;
- }
- Navigation.navigate(internalNewExpensifyPath);
- return;
- }
-
- // If we are handling an old dot Expensify link we need to open it with openOldDotLink() so we can navigate to it with the user already logged in.
- // As attachments also use expensify.com we don't want it working the same as links.
- if (internalExpensifyPath && !isAttachment) {
- Link.openOldDotLink(internalExpensifyPath);
- return;
- }
- Link.openExternalLink(attrHref);
- };
+ const internalNewExpensifyPath = Link.getInternalNewExpensifyPath(attrHref);
+ const internalExpensifyPath = Link.getInternalExpensifyPath(attrHref);
if (!HTMLEngineUtils.isChildOfComment(props.tnode)) {
// This is not a comment from a chat, the AnchorForCommentsOnly uses a Pressable to create a context menu on right click.
@@ -78,7 +31,7 @@ function AnchorRenderer(props) {
return (
Link.openLink(attrHref, environmentURL, isAttachment)}
suppressHighlighting
>
@@ -109,7 +62,7 @@ function AnchorRenderer(props) {
key={props.key}
displayName={displayName}
// Only pass the press handler for internal links. For public links or whitelisted internal links fallback to default link handling
- onPress={internalNewExpensifyPath || internalExpensifyPath ? navigateToLink : undefined}
+ onPress={internalNewExpensifyPath || internalExpensifyPath ? Link.openLink : undefined}
>
diff --git a/src/components/TextLink.js b/src/components/TextLink.js
index ab59f6f8b121..46c074eb79e6 100644
--- a/src/components/TextLink.js
+++ b/src/components/TextLink.js
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import _ from 'underscore';
+import useEnvironment from '@hooks/useEnvironment';
import stylePropTypes from '@styles/stylePropTypes';
import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
@@ -37,6 +38,7 @@ const defaultProps = {
};
function TextLink(props) {
+ const {environmentURL} = useEnvironment();
const styles = useThemeStyles();
const rest = _.omit(props, _.keys(propTypes));
const additionalStyles = _.isArray(props.style) ? props.style : [props.style];
@@ -51,7 +53,7 @@ function TextLink(props) {
return;
}
- Link.openExternalLink(props.href);
+ Link.openLink(props.href, environmentURL);
};
/**
diff --git a/src/languages/en.ts b/src/languages/en.ts
index b03e5d228a55..817f06f6b344 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1133,6 +1133,10 @@ export default {
year: 'Year',
selectYear: 'Please select a year',
},
+ focusModeUpdateModal: {
+ title: 'Welcome to #focus mode!',
+ prompt: "Read chats will be hidden, unless they have a green dot, which means there's an action you need to take on them. You can change this in your account settings ",
+ },
notFound: {
chatYouLookingForCannotBeFound: 'The chat you are looking for cannot be found.',
getMeOutOfHere: 'Get me out of here',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c6bc77681b21..b219021daa0f 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1133,6 +1133,10 @@ export default {
year: 'Año',
selectYear: 'Por favor, selecciona un año',
},
+ focusModeUpdateModal: {
+ title: '¡Bienvenido al modo #concentración!',
+ prompt: 'Los mensajes leídos se ocultarán, a menos que tengan un punto verde, lo que significa que tienes que tomar una acción en ellos. Puedes cambiar esto en la configuración de tu cuenta ',
+ },
notFound: {
chatYouLookingForCannotBeFound: 'El chat que estás buscando no se pudo encontrar.',
getMeOutOfHere: 'Sácame de aquí',
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js
index 4c610bc12099..de334635da54 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.js
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.js
@@ -20,6 +20,7 @@ import * as App from '@userActions/App';
import * as Download from '@userActions/Download';
import * as Modal from '@userActions/Modal';
import * as PersonalDetails from '@userActions/PersonalDetails';
+import * as PriorityMode from '@userActions/PriorityMode';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
import Timing from '@userActions/Timing';
@@ -194,6 +195,8 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio
App.reconnectApp(lastUpdateIDAppliedToClient);
}
+ PriorityMode.autoSwitchToFocusMode();
+
App.setUpPoliciesAndNavigate(session);
App.redirectThirdPartyDesktopSignIn();
diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index d741ced6dc08..5ee15c1cd1d0 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -2,8 +2,12 @@ import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import asyncOpenURL from '@libs/asyncOpenURL';
import * as Environment from '@libs/Environment/Environment';
+import Navigation from '@libs/Navigation/Navigation';
import * as Url from '@libs/Url';
+import CONFIG from '@src/CONFIG';
+import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
let isNetworkOffline = false;
Onyx.connect({
@@ -56,4 +60,58 @@ function openOldDotLink(url: string) {
(oldDotURL) => oldDotURL,
);
}
-export {buildOldDotURL, openOldDotLink, openExternalLink};
+
+function getInternalNewExpensifyPath(href: string) {
+ const attrPath = Url.getPathFromURL(href);
+ return (Url.hasSameExpensifyOrigin(href, CONST.NEW_EXPENSIFY_URL) || Url.hasSameExpensifyOrigin(href, CONST.STAGING_NEW_EXPENSIFY_URL) || href.startsWith(CONST.DEV_NEW_EXPENSIFY_URL)) &&
+ !CONST.PATHS_TO_TREAT_AS_EXTERNAL.find((path) => path === attrPath)
+ ? attrPath
+ : '';
+}
+
+function getInternalExpensifyPath(href: string) {
+ const attrPath = Url.getPathFromURL(href);
+ const hasExpensifyOrigin = Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.EXPENSIFY_URL) || Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.STAGING_API_ROOT);
+ if (!hasExpensifyOrigin || attrPath.startsWith(CONFIG.EXPENSIFY.CONCIERGE_URL_PATHNAME) || attrPath.startsWith(CONFIG.EXPENSIFY.DEVPORTAL_URL_PATHNAME)) {
+ return '';
+ }
+
+ return attrPath;
+}
+
+function openLink(href: string, environmentURL: string, isAttachment = false) {
+ const hasSameOrigin = Url.hasSameExpensifyOrigin(href, environmentURL);
+ const hasExpensifyOrigin = Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.EXPENSIFY_URL) || Url.hasSameExpensifyOrigin(href, CONFIG.EXPENSIFY.STAGING_API_ROOT);
+ const internalNewExpensifyPath = getInternalNewExpensifyPath(href);
+ const internalExpensifyPath = getInternalExpensifyPath(href);
+
+ // There can be messages from Concierge with links to specific NewDot reports. Those URLs look like this:
+ // https://www.expensify.com.dev/newdotreport?reportID=3429600449838908 and they have a target="_blank" attribute. This is so that when a user is on OldDot,
+ // clicking on the link will open the chat in NewDot. However, when a user is in NewDot and clicks on the concierge link, the link needs to be handled differently.
+ // Normally, the link would be sent to Link.openOldDotLink() and opened in a new tab, and that's jarring to the user. Since the intention is to link to a specific NewDot chat,
+ // the reportID is extracted from the URL and then opened as an internal link, taking the user straight to the chat in the same tab.
+ if (hasExpensifyOrigin && href.indexOf('newdotreport?reportID=') > -1) {
+ const reportID = href.split('newdotreport?reportID=').pop();
+ const reportRoute = ROUTES.REPORT_WITH_ID.getRoute(reportID ?? '');
+ Navigation.navigate(reportRoute);
+ return;
+ }
+
+ // If we are handling a New Expensify link then we will assume this should be opened by the app internally. This ensures that the links are opened internally via react-navigation
+ // instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag)
+ if (internalNewExpensifyPath && hasSameOrigin) {
+ Navigation.navigate(internalNewExpensifyPath);
+ return;
+ }
+
+ // If we are handling an old dot Expensify link we need to open it with openOldDotLink() so we can navigate to it with the user already logged in.
+ // As attachments also use expensify.com we don't want it working the same as links.
+ if (internalExpensifyPath && !isAttachment) {
+ openOldDotLink(internalExpensifyPath);
+ return;
+ }
+
+ openExternalLink(href);
+}
+
+export {buildOldDotURL, openOldDotLink, openExternalLink, openLink, getInternalNewExpensifyPath, getInternalExpensifyPath};
diff --git a/src/libs/actions/PriorityMode.ts b/src/libs/actions/PriorityMode.ts
new file mode 100644
index 000000000000..d528c31d7453
--- /dev/null
+++ b/src/libs/actions/PriorityMode.ts
@@ -0,0 +1,138 @@
+import debounce from 'lodash/debounce';
+import Onyx, {OnyxCollection} from 'react-native-onyx';
+import * as CollectionUtils from '@libs/CollectionUtils';
+import Log from '@libs/Log';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {Report} from '@src/types/onyx';
+
+/**
+ * This actions file is used to automatically switch a user into #focus mode when they exceed a certain number of reports. We do this primarily for performance reasons.
+ * Similar to the "Welcome action" we must wait for a number of things to happen when the user signs in or refreshes the page:
+ *
+ * - NVP that tracks whether they have already been switched over. We only do this once.
+ * - Priority mode NVP (that dictates the ordering/filtering logic of the LHN)
+ * - Reports to load (in ReconnectApp or OpenApp). As we check the count of the reports to determine whether the user is eligible to be automatically switched.
+ */
+
+let resolveIsReadyPromise: (args?: unknown[]) => void;
+let isReadyPromise = new Promise((resolve) => {
+ resolveIsReadyPromise = resolve;
+});
+
+let currentUserAccountID: number | undefined | null;
+Onyx.connect({
+ key: ONYXKEYS.SESSION,
+ callback: (val) => {
+ currentUserAccountID = val?.accountID;
+ },
+});
+
+/**
+ * Debounce the prompt to promote focus mode as many reports updates could happen in a short burst
+ */
+// eslint-disable-next-line @typescript-eslint/no-use-before-define
+const autoSwitchToFocusMode = debounce(tryFocusModeUpdate, 300, {leading: true});
+
+let allReports: OnyxCollection | undefined;
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT,
+ callback: (report, key) => {
+ if (!key || !report) {
+ return;
+ }
+
+ if (!allReports) {
+ allReports = {};
+ }
+
+ const reportID = CollectionUtils.extractCollectionItemID(key);
+
+ allReports[reportID] = report;
+
+ // Each time a new report is added we will check to see if the user should be switched
+ autoSwitchToFocusMode();
+ },
+});
+
+let isLoadingReportData = true;
+Onyx.connect({
+ key: ONYXKEYS.IS_LOADING_REPORT_DATA,
+ initWithStoredValues: false,
+ callback: (value) => {
+ isLoadingReportData = value ?? false;
+
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
+ checkRequiredData();
+ },
+});
+
+let isInFocusMode: boolean | undefined;
+Onyx.connect({
+ key: ONYXKEYS.NVP_PRIORITY_MODE,
+ callback: (priorityMode) => {
+ isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD;
+
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
+ checkRequiredData();
+ },
+});
+
+let hasTriedFocusMode: boolean | undefined | null;
+Onyx.connect({
+ key: ONYXKEYS.NVP_TRY_FOCUS_MODE,
+ callback: (val) => {
+ hasTriedFocusMode = val;
+
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
+ checkRequiredData();
+ },
+});
+
+function resetHasReadRequiredDataFromStorage() {
+ // Create a new promise and a new resolve function
+ isReadyPromise = new Promise((resolve) => {
+ resolveIsReadyPromise = resolve;
+ });
+ isLoadingReportData = true;
+ allReports = {};
+}
+
+function checkRequiredData() {
+ if (allReports === undefined || hasTriedFocusMode === undefined || isInFocusMode === undefined || isLoadingReportData) {
+ return;
+ }
+
+ resolveIsReadyPromise();
+}
+
+function tryFocusModeUpdate() {
+ isReadyPromise.then(() => {
+ // User is signed out so do not try to switch them
+ if (!currentUserAccountID) {
+ return;
+ }
+
+ // Check to see if the user is using #focus mode, has tried it before, or we have already switched them over automatically.
+ if ((isInFocusMode ?? false) || hasTriedFocusMode) {
+ Log.info('Not switching user to optimized focus mode.', false, {isInFocusMode, hasTriedFocusMode});
+ return;
+ }
+
+ const reportCount = Object.keys(allReports ?? {}).length;
+ if (reportCount < CONST.REPORT.MAX_COUNT_BEFORE_FOCUS_UPDATE) {
+ Log.info('Not switching user to optimized focus mode as they do not have enough reports', false, {reportCount});
+ return;
+ }
+
+ Log.info('Switching user to optimized focus mode', false, {reportCount, hasTriedFocusMode, isInFocusMode});
+
+ // Record that we automatically switched them so we don't ask again.
+ hasTriedFocusMode = true;
+
+ // Setting this triggers a modal to open and notify the user.
+ Onyx.set(ONYXKEYS.FOCUS_MODE_NOTIFICATION, true);
+ });
+}
+
+export {resetHasReadRequiredDataFromStorage, autoSwitchToFocusMode};
diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts
index 559f60a21c98..82b51651cacc 100644
--- a/src/libs/actions/Session/index.ts
+++ b/src/libs/actions/Session/index.ts
@@ -15,6 +15,7 @@ import * as ReportUtils from '@libs/ReportUtils';
import Timers from '@libs/Timers';
import {hideContextMenu} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import * as Device from '@userActions/Device';
+import * as PriorityMode from '@userActions/PriorityMode';
import redirectToSignIn from '@userActions/SignInRedirect';
import Timing from '@userActions/Timing';
import * as Welcome from '@userActions/Welcome';
@@ -589,6 +590,7 @@ function cleanupSession() {
Pusher.disconnect();
Timers.clearAll();
Welcome.resetReadyCheck();
+ PriorityMode.resetHasReadRequiredDataFromStorage();
}
function clearAccountMessages() {
diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js
index ad6fd7be10dd..1bd1cb0b763b 100644
--- a/src/libs/actions/User.js
+++ b/src/libs/actions/User.js
@@ -583,8 +583,10 @@ function updateFrequentlyUsedEmojis(frequentlyUsedEmojis) {
/**
* Sync user chat priority mode with Onyx and Server
* @param {String} mode
+ * @param {boolean} [automatic] if we changed the mode automatically
*/
-function updateChatPriorityMode(mode) {
+function updateChatPriorityMode(mode, automatic = false) {
+ const autoSwitchedToFocusMode = mode === CONST.PRIORITY_MODE.GSD && automatic;
const optimisticData = [
{
onyxMethod: Onyx.METHOD.MERGE,
@@ -592,14 +594,31 @@ function updateChatPriorityMode(mode) {
value: mode,
},
];
+
+ if (autoSwitchedToFocusMode) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: ONYXKEYS.NVP_TRY_FOCUS_MODE,
+ value: true,
+ });
+ }
+
API.write(
'UpdateChatPriorityMode',
{
value: mode,
+ automatic,
},
{optimisticData},
);
- Navigation.goBack(ROUTES.SETTINGS_PREFERENCES);
+
+ if (!autoSwitchedToFocusMode) {
+ Navigation.goBack(ROUTES.SETTINGS_PREFERENCES);
+ }
+}
+
+function clearFocusModeNotification() {
+ Onyx.set(ONYXKEYS.FOCUS_MODE_NOTIFICATION, false);
}
/**
@@ -843,6 +862,7 @@ function clearDraftCustomStatus() {
}
export {
+ clearFocusModeNotification,
closeAccount,
resendValidateCode,
requestContactMethodValidateCode,