diff --git a/android/app/build.gradle b/android/app/build.gradle index e3f4e9bb9f0d..7b8271cfcbf2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001047001 - versionName "1.4.70-1" + versionCode 1001047002 + versionName "1.4.70-2" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/assets/animations/Plane.lottie b/assets/animations/Plane.lottie new file mode 100644 index 000000000000..5244cb7bea10 Binary files /dev/null and b/assets/animations/Plane.lottie differ diff --git a/assets/images/simple-illustrations/simple-illustration__alert.svg b/assets/images/simple-illustrations/simple-illustration__alert.svg new file mode 100644 index 000000000000..2e7bca02f5e3 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__alert.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__piggybank.svg b/assets/images/simple-illustrations/simple-illustration__piggybank.svg index a9cf2b02c5dc..be87ff34752a 100644 --- a/assets/images/simple-illustrations/simple-illustration__piggybank.svg +++ b/assets/images/simple-illustrations/simple-illustration__piggybank.svg @@ -1,50 +1,50 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/suitcase.svg b/assets/images/suitcase.svg new file mode 100644 index 000000000000..97036db6b5ac --- /dev/null +++ b/assets/images/suitcase.svg @@ -0,0 +1,3 @@ + + + diff --git a/desktop/ELECTRON_EVENTS.ts b/desktop/ELECTRON_EVENTS.ts index de0bd655e12c..607ad7b21580 100644 --- a/desktop/ELECTRON_EVENTS.ts +++ b/desktop/ELECTRON_EVENTS.ts @@ -9,6 +9,7 @@ const ELECTRON_EVENTS = { KEYBOARD_SHORTCUTS_PAGE: 'keyboard-shortcuts-page', START_UPDATE: 'start-update', UPDATE_DOWNLOADED: 'update-downloaded', + SILENT_UPDATE: 'silent-update', } as const; export default ELECTRON_EVENTS; diff --git a/desktop/contextBridge.ts b/desktop/contextBridge.ts index 689c69de0cc8..487e528a7485 100644 --- a/desktop/contextBridge.ts +++ b/desktop/contextBridge.ts @@ -16,6 +16,7 @@ const WHITELIST_CHANNELS_RENDERER_TO_MAIN = [ ELECTRON_EVENTS.REQUEST_VISIBILITY, ELECTRON_EVENTS.START_UPDATE, ELECTRON_EVENTS.LOCALE_UPDATED, + ELECTRON_EVENTS.SILENT_UPDATE, ] as const; const WHITELIST_CHANNELS_MAIN_TO_RENDERER = [ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE, ELECTRON_EVENTS.UPDATE_DOWNLOADED, ELECTRON_EVENTS.FOCUS, ELECTRON_EVENTS.BLUR] as const; diff --git a/desktop/main.ts b/desktop/main.ts index 6e14d661b345..b40557464ec1 100644 --- a/desktop/main.ts +++ b/desktop/main.ts @@ -111,6 +111,7 @@ process.argv.forEach((arg) => { // happens correctly. let hasUpdate = false; let downloadedVersion: string; +let isSilentUpdating = false; // Note that we have to subscribe to this separately and cannot use Localize.translateLocal, // because the only way code can be shared between the main and renderer processes at runtime is via the context bridge @@ -127,16 +128,20 @@ const quitAndInstallWithUpdate = () => { autoUpdater.quitAndInstall(); }; -/** Menu Item callback to triggers an update check */ -const manuallyCheckForUpdates = (menuItem: MenuItem, browserWindow?: BrowserWindow) => { - // Disable item until the check (and download) is complete - // eslint: menu item flags like enabled or visible can be dynamically toggled by mutating the object - // eslint-disable-next-line no-param-reassign - menuItem.enabled = false; +/** Menu Item callback to trigger an update check */ +const manuallyCheckForUpdates = (menuItem?: MenuItem, browserWindow?: BrowserWindow) => { + if (menuItem) { + // Disable item until the check (and download) is complete + // eslint-disable-next-line no-param-reassign -- menu item flags like enabled or visible can be dynamically toggled by mutating the object + menuItem.enabled = false; + } autoUpdater .checkForUpdates() - .catch((error) => ({error})) + .catch((error) => { + isSilentUpdating = false; + return {error}; + }) .then((result) => { const downloadPromise = result && 'downloadPromise' in result ? result.downloadPromise : undefined; @@ -148,7 +153,7 @@ const manuallyCheckForUpdates = (menuItem: MenuItem, browserWindow?: BrowserWind dialog.showMessageBox(browserWindow, { type: 'info', message: Localize.translate(preferredLocale, 'checkForUpdatesModal.available.title'), - detail: Localize.translate(preferredLocale, 'checkForUpdatesModal.available.message'), + detail: Localize.translate(preferredLocale, 'checkForUpdatesModal.available.message', {isSilentUpdating}), buttons: [Localize.translate(preferredLocale, 'checkForUpdatesModal.available.soundsGood')], }); } else if (result && 'error' in result && result.error) { @@ -172,6 +177,10 @@ const manuallyCheckForUpdates = (menuItem: MenuItem, browserWindow?: BrowserWind return downloadPromise; }) .finally(() => { + isSilentUpdating = false; + if (!menuItem) { + return; + } // eslint-disable-next-line no-param-reassign menuItem.enabled = true; }); @@ -201,7 +210,7 @@ const electronUpdater = (browserWindow: BrowserWindow): PlatformSpecificUpdater if (checkForUpdatesMenuItem) { checkForUpdatesMenuItem.visible = false; } - if (browserWindow.isVisible()) { + if (browserWindow.isVisible() && !isSilentUpdating) { browserWindow.webContents.send(ELECTRON_EVENTS.UPDATE_DOWNLOADED, info.version); } else { quitAndInstallWithUpdate(); @@ -604,6 +613,15 @@ const mainWindow = (): Promise => { } }); + // Automatically check for and install the latest version in the background + ipcMain.on(ELECTRON_EVENTS.SILENT_UPDATE, () => { + if (isSilentUpdating) { + return; + } + isSilentUpdating = true; + manuallyCheckForUpdates(undefined, browserWindow); + }); + return browserWindow; }) diff --git a/docs/articles/expensify-classic/expensify-billing/Billing-Overview.md b/docs/articles/expensify-classic/expensify-billing/Billing-Overview.md index ed44caad546b..a998e279c3f6 100644 --- a/docs/articles/expensify-classic/expensify-billing/Billing-Overview.md +++ b/docs/articles/expensify-classic/expensify-billing/Billing-Overview.md @@ -23,7 +23,7 @@ Bundling the Expensify Card with an annual subscription ensures you pay the lowe If at least 50% of your approved USD spend in a given month is on your company’s Expensify Cards, you will receive an additional 50% discount on the price per member. This additional 50% discount, when coupled with an annual subscription, brings the price per member to $5 on a Collect plan and $9 on a Control plan. -Additionally, every month, you receive 1% cash back on all Expensify Card purchases, and 2% if the spend across your Expensify Cards is $250k or more (_applies to USD purchases only_). Any cash back from the Expensify Card is first applied to your Expensify bill, further reducing your price per member. Any leftover cash back is deposited directly into your connected bank account. +Additionally, every month, you receive 1% cash back on all Expensify Card purchases, and 2% if the spend across your Expensify Cards is $250k or more (_applies to US purchases only_). Any cash back from the Expensify Card is first applied to your Expensify bill, further reducing your price per member. Any leftover cash back is deposited directly into your connected bank account. ## Savings calculator To see how much money you can save (and even earn!) by using the Expensify Card, check out our [savings calculator](https://use.expensify.com/price-savings-calculator). Just enter a few details and see how much you’ll save! @@ -34,11 +34,9 @@ If less than 50% of your total USD spend is on the Expensify Card, the bill is d **Example:** - Annual subscription discount: 50% -- % of Expensify Card spend (USD) across all workspaces: 20% +- % of Expensify Card spend (US purchases only) across all workspaces: 20% - Expensify Card discount: 20% In that case, you'd save 70% on the price per member for that month's bill. -Note: USD spend refers to approved USD transactions on the Expensify Card in any given month. - {% include faq-end.md %} diff --git a/docs/articles/expensify-classic/workspaces/Remove-Members.md b/docs/articles/expensify-classic/workspaces/Remove-Members.md new file mode 100644 index 000000000000..a79d75edc77d --- /dev/null +++ b/docs/articles/expensify-classic/workspaces/Remove-Members.md @@ -0,0 +1,33 @@ +--- +title: Remove a Workspace Member +description: How to remove a member from a Workspace in Expensify +--- + +Removing a member from a workspace prevents them from submitting reports to or accessing the workspace. Please note that it does not delete their account or deactivate their Expensify Card. + +## Remove a Workspace Member +Important: Make sure the employee has submitted all reports, and the reports have been approved and reimbursed, and are in the final approval state. +1. Go to Settings > Workspaces > Group > [Workspace Name] > Members > Workspace Members +2. Select the member you'd like to remove and click the **Remove** button at the top of the Members table +3. If this member was an approver, update the approval workflow so that reports are no longer routed to them + +![image of members table in a workspace]({{site.url}}/assets/images/ExpensifyHelp_RemovingMembers.png){:width="100%"} + +{% include faq-begin.md %} + +## Will reports from this member on this workspace still be available? +Yes, as long as the reports have been submitted. You can navigate to the Reports page and enter the member's email in the search field to find them. However, Draft reports will be removed from the workspace, so these will no longer be visible to the Workspace Admin. + +## Can members still access their reports on a workspace after they have been removed? +Yes. Any report that has been approved will now show the workspace as “(not shared)” in their account. If it is a Draft Report they will still be able to edit it and add it to a new workspace. If the report is Approved or Reimbursed they will not be able to edit it further. + +## Who can remove members from a workspace? +Only Workspace Admins. It is not possible for a member to add or remove themselves from a workspace. It is not possible for a Domain Admin who is not also a Workspace Admin to remove a member from a workspace. + +## How do I remove a member from a workspace if I am seeing an error message? +If a member is a **preferred exporter, billing owner, report approver** or has **processing reports**, to remove them from the workspace you will first need to: + +* **Preferred Exporter**: Go to Settings > Workspaces > Group > [Workspace Name] > Connections > Configure and select a different Workspace Admin in the dropdown for **Preferred Exporter**. +* **Billing Owner**: Take over billing on the Settings > Workspaces > Group > [Workspace Name] > Overview page. +* **Processing reports**: Approve or reject the member’s reports on your Reports page. +* **Approval Workflow**: Remove them as a workflow approver on your Settings > Workspaces > Group > [Workspace Name] > Members > Approval Mode > page by changing the "**Submit reports to**" field. diff --git a/docs/redirects.csv b/docs/redirects.csv index c887b649b32d..f775d2f97094 100644 --- a/docs/redirects.csv +++ b/docs/redirects.csv @@ -169,3 +169,4 @@ https://help.expensify.com/articles/new-expensify/expenses/Referral-Program,http https://help.expensify.com/articles/expensify-classic/reports/Report-Audit-Log-and-Comments,https://help.expensify.com/articles/expensify-classic/reports/Print-or-download-a-report https://help.expensify.com/articles/expensify-classic/reports/The-Reports-Page,https://help.expensify.com/articles/expensify-classic/reports/Report-statuses https://help.expensify.com/articles/new-expensify/getting-started/Free-plan-upgrade-to-collect-plan,https://help.expensify.com/articles/new-expensify/getting-started/Upgrade-to-a-Collect-Plan +https://help.expensify.com/articles/new-expensify/bank-accounts-and-payments/Connect-a-Bank-Account,https://help.expensify.com/new-expensify/hubs/expenses/Connect-a-Bank-Account diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index a519e0ebf0dd..647c12d51353 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.70.1 + 1.4.70.2 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index b359e93157c7..c692d84e11a2 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.70.1 + 1.4.70.2 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index ab7622c2820d..8bb62f9d5f56 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.70 CFBundleVersion - 1.4.70.1 + 1.4.70.2 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 548a93ed6e51..c4c89ebb99cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.70-1", + "version": "1.4.70-2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.70-1", + "version": "1.4.70-2", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -100,7 +100,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "2.0.35", + "react-native-onyx": "2.0.32", "react-native-pager-view": "6.2.3", "react-native-pdf": "6.7.3", "react-native-performance": "^5.1.0", @@ -31431,9 +31431,9 @@ } }, "node_modules/react-native-onyx": { - "version": "2.0.35", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-2.0.35.tgz", - "integrity": "sha512-eQwXQoYpv6Wv1sDrR2Otl4mW34U8OZPtlpju3OyGv1KpQSQ+2q8Ivju7AHc3DG+j2QHypUKngQghKdJ9Sm3jBQ==", + "version": "2.0.32", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-2.0.32.tgz", + "integrity": "sha512-tB9wqMJGTLOYfrfplRP+9aq5JdD8w/hV/OZsMAVH+ewbE1zLY8OymUsAsIFdF1v+cB8HhehP569JVLZmhm6bsg==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", diff --git a/package.json b/package.json index c1b599baa952..9530389b1fb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.70-1", + "version": "1.4.70-2", "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.", @@ -152,7 +152,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "2.0.35", + "react-native-onyx": "2.0.32", "react-native-pager-view": "6.2.3", "react-native-pdf": "6.7.3", "react-native-performance": "^5.1.0", diff --git a/patches/@rnmapbox+maps+10.1.11.patch b/patches/@rnmapbox+maps+10.1.12.patch similarity index 99% rename from patches/@rnmapbox+maps+10.1.11.patch rename to patches/@rnmapbox+maps+10.1.12.patch index 5c5b8f0b69bb..c8135280056c 100644 --- a/patches/@rnmapbox+maps+10.1.11.patch +++ b/patches/@rnmapbox+maps+10.1.12.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/camera/RNMBXCamera.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/camera/RNMBXCamera.kt -index dbd6d0b..1d043f2 100644 +index 0d876a7..cceed39 100644 --- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/camera/RNMBXCamera.kt +++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/camera/RNMBXCamera.kt @@ -188,7 +188,7 @@ class RNMBXCamera(private val mContext: Context, private val mManager: RNMBXCame diff --git a/src/CONST.ts b/src/CONST.ts index 310bb3959300..566d5179f86a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -584,6 +584,7 @@ const CONST = { ONFIDO_PRIVACY_POLICY_URL: 'https://onfido.com/privacy/', ONFIDO_TERMS_OF_SERVICE_URL: 'https://onfido.com/terms-of-service/', LIST_OF_RESTRICTED_BUSINESSES: 'https://community.expensify.com/discussion/6191/list-of-restricted-businesses', + TRAVEL_TERMS_URL: `${USE_EXPENSIFY_URL}/travelterms`, // Use Environment.getEnvironmentURL to get the complete URL with port number DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', @@ -668,6 +669,7 @@ const CONST = { MANAGER_DETACH_RECEIPT: 'MANAGERDETACHRECEIPT', // OldDot Action MARKED_REIMBURSED: 'MARKEDREIMBURSED', // OldDot Action MARK_REIMBURSED_FROM_INTEGRATION: 'MARKREIMBURSEDFROMINTEGRATION', // OldDot Action + MERGED_WITH_CASH_TRANSACTION: 'MERGEDWITHCASHTRANSACTION', MODIFIED_EXPENSE: 'MODIFIEDEXPENSE', MOVED: 'MOVED', OUTDATED_BANK_ACCOUNT: 'OUTDATEDBANKACCOUNT', // OldDot Action @@ -842,7 +844,7 @@ const CONST = { }, RESERVED_ROOM_NAMES: ['#admins', '#announce'], MAX_PREVIEW_AVATARS: 4, - MAX_ROOM_NAME_LENGTH: 79, + MAX_ROOM_NAME_LENGTH: 99, LAST_MESSAGE_TEXT_MAX_LENGTH: 200, OWNER_EMAIL_FAKE: '__FAKE__', OWNER_ACCOUNT_ID_FAKE: 0, @@ -917,6 +919,15 @@ const CONST = { SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, RESIZE_DEBOUNCE_TIME: 100, }, + SEARCH_TABLE_COLUMNS: { + DATE: 'date', + MERCHANT: 'merchant', + FROM: 'from', + TO: 'to', + TOTAL: 'total', + TYPE: 'type', + ACTION: 'action', + }, PRIORITY_MODE: { GSD: 'gsd', DEFAULT: 'default', @@ -1846,7 +1857,7 @@ const CONST = { CARD_NUMBER: /^[0-9]{15,16}$/, CARD_SECURITY_CODE: /^[0-9]{3,4}$/, CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/, - ROOM_NAME: /^#[\p{Ll}0-9-]{1,80}$/u, + ROOM_NAME: /^#[\p{Ll}0-9-]{1,100}$/u, // eslint-disable-next-line max-len, no-misleading-character-class EMOJI: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, @@ -2026,7 +2037,6 @@ const CONST = { INFO: 'info', }, REPORT_DETAILS_MENU_ITEM: { - SHARE_CODE: 'shareCode', MEMBERS: 'member', INVITE: 'invite', SETTINGS: 'settings', @@ -3419,11 +3429,6 @@ const CONST = { }, TAB_SEARCH: { ALL: 'all', - // @TODO: Uncomment when the queries below are implemented - // SHARED: 'shared', - // DRAFTS: 'drafts', - // WAITING_ON_YOU: 'waitingOnYou', - // FINISHED: 'finished', }, STATUS_TEXT_MAX_LENGTH: 100, @@ -4698,6 +4703,14 @@ const CONST = { MAX_TAX_RATE_INTEGER_PLACES: 4, MAX_TAX_RATE_DECIMAL_PLACES: 4, + DOWNLOADS_PATH: '/Downloads', + NEW_EXPENSIFY_PATH: '/New Expensify', + + ENVIRONMENT_SUFFIX: { + DEV: ' Dev', + ADHOC: ' AdHoc', + }, + SEARCH_TRANSACTION_TYPE: { CASH: 'cash', CARD: 'card', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 1a27d691e2ef..88818c3eb7c6 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -282,6 +282,9 @@ const ONYXKEYS = { /** Onboarding Purpose selected by the user during Onboarding flow */ ONBOARDING_PURPOSE_SELECTED: 'onboardingPurposeSelected', + /** Onboarding Purpose selected by the user during Onboarding flow */ + ONBOARDING_ADMINS_CHAT_REPORT_ID: 'onboardingAdminsChatReportID', + // Max width supported for HTML element MAX_CANVAS_WIDTH: 'maxCanvasWidth', @@ -655,6 +658,7 @@ type OnyxValuesMapping = { [ONYXKEYS.MAX_CANVAS_HEIGHT]: number; [ONYXKEYS.MAX_CANVAS_WIDTH]: number; [ONYXKEYS.ONBOARDING_PURPOSE_SELECTED]: string; + [ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID]: string; [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: boolean; [ONYXKEYS.LAST_VISITED_PATH]: string | undefined; [ONYXKEYS.RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c274e8abdf08..3d73164802d7 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -758,8 +758,10 @@ const ROUTES = { route: 'referral/:contentType', getRoute: (contentType: string, backTo?: string) => getUrlWithBackToParam(`referral/${contentType}`, backTo), }, - TRACK_TRAINING_MODAL: 'track-training', PROCESS_MONEY_REQUEST_HOLD: 'hold-expense-educational', + TRAVEL_MY_TRIPS: 'travel', + TRAVEL_TCS: 'travel/terms', + TRACK_TRAINING_MODAL: 'track-training', ONBOARDING_ROOT: 'onboarding', ONBOARDING_PERSONAL_DETAILS: 'onboarding/personal-details', ONBOARDING_WORK: 'onboarding/work', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index e9f180a54879..d9f92382bc95 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -23,6 +23,10 @@ const SCREENS = { CONNECTION_COMPLETE: 'ConnectionComplete', UNLINK_LOGIN: 'UnlinkLogin', SETTINGS_CENTRAL_PANE: 'SettingsCentralPane', + TRAVEL: { + MY_TRIPS: 'Travel_MyTrips', + TCS: 'Travel_TCS', + }, WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane', SEARCH: { CENTRAL_PANE: 'Search_Central_Pane', @@ -133,6 +137,7 @@ const SCREENS = { ROOM_INVITE: 'RoomInvite', REFERRAL: 'Referral', PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold', + TRAVEL: 'Travel', SEARCH_REPORT: 'SearchReport', }, ONBOARDING_MODAL: { diff --git a/src/components/AvatarCropModal/ImageCropView.tsx b/src/components/AvatarCropModal/ImageCropView.tsx index c79a209376b4..b7f2a64090d6 100644 --- a/src/components/AvatarCropModal/ImageCropView.tsx +++ b/src/components/AvatarCropModal/ImageCropView.tsx @@ -86,6 +86,7 @@ function ImageCropView({imageUri = '', containerSize = 0, panGesture = Gesture.P // fill={theme.iconReversed} width={containerSize} height={containerSize} + key={containerSize} /> diff --git a/src/components/ChatDetailsQuickActionsBar.tsx b/src/components/ChatDetailsQuickActionsBar.tsx index f15fc31aec45..d289587ce953 100644 --- a/src/components/ChatDetailsQuickActionsBar.tsx +++ b/src/components/ChatDetailsQuickActionsBar.tsx @@ -1,11 +1,12 @@ -import React, {useState} from 'react'; +import React from 'react'; import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; import * as Report from '@userActions/Report'; +import ROUTES from '@src/ROUTES'; import type {Report as OnyxReportType} from '@src/types/onyx'; import Button from './Button'; -import ConfirmModal from './ConfirmModal'; import * as Expensicons from './Icon/Expensicons'; type ChatDetailsQuickActionsBarProps = { @@ -14,45 +15,26 @@ type ChatDetailsQuickActionsBarProps = { function ChatDetailsQuickActionsBar({report}: ChatDetailsQuickActionsBarProps) { const styles = useThemeStyles(); - const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false); const {translate} = useLocalize(); const isPinned = !!report.isPinned; return ( - { - setIsLastMemberLeavingGroupModalVisible(false); - Report.leaveGroupChat(report.reportID); - }} - onCancel={() => setIsLastMemberLeavingGroupModalVisible(false)} - prompt={translate('groupChat.lastMemberWarning')} - confirmText={translate('common.leave')} - cancelText={translate('common.cancel')} - /> diff --git a/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx b/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx index fcad770908a6..7c4c669e2154 100644 --- a/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx +++ b/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx @@ -30,9 +30,11 @@ type BaseClientSideLoggingToolProps = { onDisableLogging: (logs: Log[]) => void; /** Action to run when enabling logging */ onEnableLogging?: () => void; + /** Path used to display location of saved file */ + displayPath?: string; } & BaseClientSideLoggingToolMenuOnyxProps; -function BaseClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs, file, onShareLogs, onDisableLogging, onEnableLogging}: BaseClientSideLoggingToolProps) { +function BaseClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs, file, onShareLogs, onDisableLogging, onEnableLogging, displayPath}: BaseClientSideLoggingToolProps) { const {translate} = useLocalize(); const onToggle = () => { @@ -70,7 +72,7 @@ function BaseClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs, file, onS {!!file && ( <> - {`path: ${file.path}`} + {`path: ${displayPath}`} {!!pathIOS && ( <> - {`path: ${pathIOS}`} + {`path: ${displayPath}/${newFileName}`}