diff --git a/android/app/build.gradle b/android/app/build.gradle
index af7f43adad0d..6827448c5053 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -91,8 +91,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001039900
- versionName "1.3.99-0"
+ versionCode 1001040000
+ versionName "1.4.0-0"
}
flavorDimensions "default"
diff --git a/docs/articles/expensify-classic/expense-and-report-features/The-Expenses-Page.md b/docs/articles/expensify-classic/expense-and-report-features/The-Expenses-Page.md
index 42a8a914e5bc..5431355dd790 100644
--- a/docs/articles/expensify-classic/expense-and-report-features/The-Expenses-Page.md
+++ b/docs/articles/expensify-classic/expense-and-report-features/The-Expenses-Page.md
@@ -66,7 +66,7 @@ A Workspace admin can see Processing, Approved, and Reimbursed expenses as long
If employees submit expense reports on a workspace where you are not an admin, you will not have visibility into those expenses. Additionally, if an expense is left unreported, a workspace admin will not be able to see that expense until it’s been added to a report.
A Workspace admin can edit the tags and categories on an expense, but if they want to edit the amount, date, or merchant name, the expense will need to be in a Processing state or rejected back to the submitter for changes.
-We have more about company card expense reconciliation in this support article.
+We have more about company card expense reconciliation in this [support article](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Reconciliation).
## Can I edit multiple expenses at once?
Yes! Select the expenses you want to edit and click **Edit Multiple**.
diff --git a/docs/articles/new-expensify/getting-started/Expensify-Lounge.md b/docs/articles/new-expensify/getting-started/Expensify-Lounge.md
deleted file mode 100644
index bdccbe927769..000000000000
--- a/docs/articles/new-expensify/getting-started/Expensify-Lounge.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: Welcome to the Expensify Lounge!
-description: How to get the most out of the Expensify Lounge.
-redirect_from: articles/other/Expensify-Lounge/
----
-
-
-# What is the Expensify Lounge?
-The Expensify Lounge is a place where people go to Get Shit Done. It's a beautiful environment with great coffee and a group of people to collaborate with. Check out this guide on how to best utilize the Expensify Lounge!
-
-# The Two Rules
-### Rule #1 - Get Shit Done
-
-The Lounge is a space for people to get work done. It is optimized to be the perfect environment for you to focus on your work, collaborate with others, and advance your most wild and creative ideas. To make this a reality, we ask our members to keep the following in mind:
-
-- **#focus** - Use the space for how it was designed and do not distract from others' focus. The space is beautiful, social, and collaborative, but it was created to help our members work effectively.
-- **#urgency** - Working remotely is great, but there's nothing like real-time collaboration with your colleagues. Use the lounge to meet with co-workers IRL to continue the progress on whatever it is you're working on.
-- **#results** - Don't mistake time for effort or effort for output. Upon arrival, visualize what you want to accomplish, and don't leave until it's done.
-
-## Rule #2 - Don’t Ruin it for Everyone Else
-
-We want this place to be incredible, innovative, and always elvoving. To achieve that, we have some general guidelines:
-
-- **#writeitdown** - If you can help others learn from you, do so. Write a blog post, a document, or a post in Expensify Chat to share with others. This includes making the Expensify Lounge a better space. Feel free to write down any improvements so we can make it better.
-- **#showup** - If you are in the lounge, be fully present. Meet others, and collaborate in social rooms. The point is to build a community of people who are focused on getting shit done; you’ll get out what you put in.
-- **#oneteam** - Providing an inclusive community is our priority, and we do not tolerate any form of discrimination. Aim to go out of your way to include people who want to be included.
-- **#nocreeps** - Do not make people feel uncomfortable with your words or actions. If you are made to feel uncomfortable or notice this happening to someone else, you can use the escalation process outlined in the FAQ section.
-
-# How to Use the Expensify Lounge
-Keeping those two rules in mind, below is a guide on how our members can get the most out of the lounge.
-
-### Rule #1 - Getting Shit Done
-- **Order drinks from Concierge** - [Write Concierge here](https://new.expensify.com/concierge) to ask lounge questions or order beverages. Concierge will bring your order directly to you!
-- **Using an office** - Offices are first come, first serve. If an office is open, feel free to use it! Please keep office use to under an hour. We currently do not allow reserving offices.
-- **Lounge hours** - The lounge will be open from 8am-6pm PT, Monday through Friday and closed on some major holidays. You can review our Google Maps profile to check our holiday hours.
-- **Make the lounge better** - Make any suggestions to improve the lounge experience in [#announce - Expensify Lounge](https://new.expensify.com/r/8292963527436014).
-
-## Rule #2 - Not Ruining it for Everyone Else
-- **Offices are for calls** - Please do not occupy an office unless you have a call or collaborative meeting happening, and don't stay in an office for longer than an hour.
-- **Respect other people** - Please do not be too loud or distracting while others are trying to work. While collaborating in Expensify Chat, be respectful of others’ viewpoints and keep a positive environment.
-- **Stay home if you’re sick** - If you feel sick, please do not visit the lounge, or consider wearing a mask in public areas.
-- **If you see something, say something** - If you are made to feel uncomfortable or witness others being made uncomfortable, let Concierge know. If this is happening in Expensify Chat, use our moderation tools (outlined below in the FAQ) to apply the applicable level of moderation.
-
-We’re so happy you are here to live rich, have fun, and save the world with us. Now, go enjoy the Expensify Lounge, and let's Get Shit Done!
-
-# FAQs
-
-#### What is Concierge?
-
-Concierge is our automated system that answers member questions in real-time. Questions regarding the local lounge will be routed directly to the lounge's Concierge. You can send Concierge a message if you have a drink request or general questions. They’ll take care of everything for you!
-
-#### Who is invited to the Expensify Lounge?
-
-Everyone is invited to the Expensify Lounge! Whether you're an existing customer, or you're someone looking for a great space to Get Shit Done, we'd love to have you.
-
-#### How do I escalate something that's making me or someone else uncomfortable?
-
-If you see something in Expensify Chat that should be escalated, you can use the escalation feature to mark a chat as:
-- **Spam or Inconsiderate**: This will send a whisper to the sender of the message warning them of the violation, and the message will have a flag applied to it which will be visible to all users. Concierge will not review these flags.
-- **Intimidating or Bullying**: The message will be immediately hidden, and the content will be reviewed by our team. After reviewing the message, and it's confirmed intimidation or bullying, the message will be permanently hidden and we'll communicate the violation to the sender of the message.
-- **Harassment or Assault**: The message will be immediately hidden and reviewed by our team. The user will be sent a message to warning them of the violation, and Concierge can block the user if that's deemed necessary.
-
-If you witness something in-person, please write to Concierge referencing which lounge you are in, and they will escalate the issue appropriately.
-
-#### Where are other Expensify Lounge locations?
-
-Right now, we only have the San Francisco Lounge, but be on the lookout for more coming soon!
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index d40d36701731..0de3f7cb2671 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.3.99
+ 1.4.0
CFBundleSignature
????
CFBundleURLTypes
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.3.99.0
+ 1.4.0.0
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 4e3ca3ebce6d..cd8b9bd630c8 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.3.99
+ 1.4.0
CFBundleSignature
????
CFBundleVersion
- 1.3.99.0
+ 1.4.0.0
diff --git a/package-lock.json b/package-lock.json
index b34cde433719..fae3dbb10ed7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.3.99-0",
+ "version": "1.4.0-0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.3.99-0",
+ "version": "1.4.0-0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index e68f10940d6a..b7e2f5ad8515 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.3.99-0",
+ "version": "1.4.0-0",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
index 8f215fefd71b..45cdb340cc98 100644
--- a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
+++ b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
@@ -8,7 +8,7 @@ import styles from '@styles/styles';
type DisplayNamesTooltipItemProps = {
index?: number;
- /** The full title of the DisplayNames component (not split up) */
+ /** The function to get a distance to shift the tooltip horizontally */
getTooltipShiftX?: (index: number) => number | undefined;
/** The Account ID for the tooltip */
diff --git a/src/components/MapView/MapView.web.tsx b/src/components/MapView/MapView.web.tsx
index d706168f076f..110d24f0c087 100644
--- a/src/components/MapView/MapView.web.tsx
+++ b/src/components/MapView/MapView.web.tsx
@@ -19,9 +19,10 @@ import utils from './utils';
const MapView = forwardRef(
({style, styleURL, waypoints, mapPadding, accessToken, directionCoordinates, initialState = {location: CONST.MAPBOX.DEFAULT_COORDINATE, zoom: CONST.MAPBOX.DEFAULT_ZOOM}}, ref) => {
const [mapRef, setMapRef] = useState(null);
+ const [shouldResetBoundaries, setShouldResetBoundaries] = useState(false);
const setRef = useCallback((newRef: MapRef | null) => setMapRef(newRef), []);
- useEffect(() => {
+ const resetBoundaries = useCallback(() => {
if (!waypoints || waypoints.length === 0) {
return;
}
@@ -47,6 +48,18 @@ const MapView = forwardRef(
map.fitBounds([northEast, southWest], {padding: mapPadding});
}, [waypoints, mapRef, mapPadding, directionCoordinates]);
+ useEffect(resetBoundaries, [resetBoundaries]);
+
+ useEffect(() => {
+ if (!shouldResetBoundaries) {
+ return;
+ }
+
+ resetBoundaries();
+ setShouldResetBoundaries(false);
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- this effect only needs to run when the boundaries reset is forced
+ }, [shouldResetBoundaries]);
+
useEffect(() => {
if (!mapRef) {
return;
@@ -54,6 +67,7 @@ const MapView = forwardRef(
const resizeObserver = new ResizeObserver(() => {
mapRef.resize();
+ setShouldResetBoundaries(true);
});
resizeObserver.observe(mapRef.getContainer());
diff --git a/src/components/withLocalize.js b/src/components/withLocalize.tsx
similarity index 53%
rename from src/components/withLocalize.js
rename to src/components/withLocalize.tsx
index 346d402829bd..040ec509135e 100755
--- a/src/components/withLocalize.js
+++ b/src/components/withLocalize.tsx
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
-import React, {forwardRef} from 'react';
+import React, {ComponentType, ForwardedRef, forwardRef, ReactElement, RefAttributes} from 'react';
import getComponentDisplayName from '@libs/getComponentDisplayName';
-import {LocaleContext} from './LocaleContextProvider';
+import {LocaleContext, LocaleContextProps} from './LocaleContextProvider';
const withLocalizePropTypes = {
/** Returns translated string for given locale and phrase */
@@ -30,24 +30,30 @@ const withLocalizePropTypes = {
toLocaleDigit: PropTypes.func.isRequired,
};
-export default function withLocalize(WrappedComponent) {
- const WithLocalize = forwardRef((props, ref) => (
-
- {(translateUtils) => (
-
- )}
-
- ));
+type WithLocalizeProps = LocaleContextProps;
+
+export default function withLocalize(
+ WrappedComponent: ComponentType>,
+): (props: Omit & React.RefAttributes) => ReactElement | null {
+ function WithLocalize(props: Omit, ref: ForwardedRef) {
+ return (
+
+ {(translateUtils) => (
+
+ )}
+
+ );
+ }
WithLocalize.displayName = `withLocalize(${getComponentDisplayName(WrappedComponent)})`;
-
- return WithLocalize;
+ return forwardRef(WithLocalize);
}
export {withLocalizePropTypes};
+export type {WithLocalizeProps};
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 9861a6de870d..bcae03964155 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -4226,6 +4226,15 @@ function getRoom(type, policyID) {
const room = _.find(allReports, (report) => report && report.policyID === policyID && report.chatType === type && !isThread(report));
return room;
}
+/**
+ * We only want policy owners and admins to be able to modify the welcome message, but not in thread chat.
+ * @param {Object} report
+ * @param {Object} policy
+ * @return {Boolean}
+ */
+function shouldDisableWelcomeMessage(report, policy) {
+ return isMoneyRequestReport(report) || isArchivedRoom(report) || !isChatRoom(report) || isChatThread(report) || !PolicyUtils.isPolicyAdmin(policy);
+}
export {
getReportParticipantsTitle,
@@ -4389,4 +4398,5 @@ export {
getPersonalDetailsForAccountID,
getRoom,
getActorNameForPreviewMessage,
+ shouldDisableWelcomeMessage,
};
diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.js
index c748e36c98e6..c9bd65a11318 100644
--- a/src/pages/ReportWelcomeMessagePage.js
+++ b/src/pages/ReportWelcomeMessagePage.js
@@ -13,7 +13,7 @@ import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import * as PolicyUtils from '@libs/PolicyUtils';
+import * as ReportUtils from '@libs/ReportUtils';
import updateMultilineInputRange from '@libs/UpdateMultilineInputRange';
import styles from '@styles/styles';
import * as Report from '@userActions/Report';
@@ -80,7 +80,7 @@ function ReportWelcomeMessagePage(props) {
includeSafeAreaPaddingBottom={false}
testID={ReportWelcomeMessagePage.displayName}
>
-
+
Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(props.report.reportID))}
diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.js b/src/pages/settings/Profile/CustomStatus/StatusPage.js
index 78aa71db6256..25dc9dcbb6bd 100644
--- a/src/pages/settings/Profile/CustomStatus/StatusPage.js
+++ b/src/pages/settings/Profile/CustomStatus/StatusPage.js
@@ -49,7 +49,15 @@ function StatusPage({draftStatus, currentUserPersonalDetails}) {
User.clearDraftCustomStatus();
};
- const navigateBackToSettingsPage = useCallback(() => Navigation.goBack(ROUTES.SETTINGS_PROFILE, false, true), []);
+ const navigateBackToSettingsPage = useCallback(() => {
+ const topMostReportID = Navigation.getTopmostReportId();
+ if (topMostReportID) {
+ Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(topMostReportID));
+ } else {
+ Navigation.goBack(ROUTES.SETTINGS_PROFILE, false, true);
+ }
+ }, []);
+
const updateStatus = useCallback(() => {
User.updateCustomStatus({text: defaultText, emojiCode: defaultEmoji});
diff --git a/src/pages/settings/Report/ReportSettingsPage.js b/src/pages/settings/Report/ReportSettingsPage.js
index c89e08c8c7b3..cea9296055c7 100644
--- a/src/pages/settings/Report/ReportSettingsPage.js
+++ b/src/pages/settings/Report/ReportSettingsPage.js
@@ -62,9 +62,8 @@ function ReportSettingsPage(props) {
const shouldDisableRename = useMemo(() => ReportUtils.shouldDisableRename(report, linkedWorkspace), [report, linkedWorkspace]);
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
- // We only want policy owners and admins to be able to modify the welcome message.
- const shouldDisableWelcomeMessage =
- isMoneyRequestReport || ReportUtils.isArchivedRoom(report) || !ReportUtils.isChatRoom(report) || _.isEmpty(linkedWorkspace) || linkedWorkspace.role !== CONST.POLICY.ROLE.ADMIN;
+ // We only want policy owners and admins to be able to modify the welcome message, but not in thread chat
+ const shouldDisableWelcomeMessage = ReportUtils.shouldDisableWelcomeMessage(report, linkedWorkspace);
const shouldDisableSettings = _.isEmpty(report) || ReportUtils.isArchivedRoom(report);
const shouldShowRoomName = !ReportUtils.isPolicyExpenseChat(report) && !ReportUtils.isChatThread(report);