diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss
index eaaa1c63badb..9276443c3813 100644
--- a/docs/_sass/_main.scss
+++ b/docs/_sass/_main.scss
@@ -712,41 +712,11 @@ button {
}
}
-#floating-concierge-button-global {
- position: fixed;
- display: block;
- @include breakpoint($breakpoint-tablet) {
- display: none;
- }
-}
-
-#floating-concierge-button-lhn {
- position: absolute;
- display: none;
- @include breakpoint($breakpoint-tablet) {
- display: block;
- }
-}
-
.get-help {
flex-wrap: wrap;
margin-top: 40px;
}
-.floating-concierge-button {
- bottom: 2rem;
- right: 2rem;
-
- img {
- width: 4rem;
- height: 4rem;
-
- &:hover {
- filter: saturate(2);
- }
- }
-}
-
.disable-scrollbar {
@media screen and (max-width: $breakpoint-tablet) {
overflow: hidden;
diff --git a/docs/articles/new-expensify/get-paid-back/Referral-Program.md b/docs/articles/new-expensify/get-paid-back/Referral-Program.md
index 683e93d0277a..34a35f5dc7c8 100644
--- a/docs/articles/new-expensify/get-paid-back/Referral-Program.md
+++ b/docs/articles/new-expensify/get-paid-back/Referral-Program.md
@@ -1,53 +1,53 @@
---
-title: Expensify Referral Program
-description: Send your joining link, submit a receipt or invoice, and we'll pay you if your referral adopts Expensify.
+title: New Expensify Referral Program
+description: Share your invite link with a friend, start a chat with a coworker, request money from your boss -- we'll pay you $250 if your referral adopts New Expensify.
---
# About
-Expensify has grown thanks to our users who love Expensify so much that they tell their friends, colleagues, managers, and fellow business founders to use it, too.
+[New Expensify](https://new.expensify.com/) is growing thanks to members like you who love it so much that they tell their friends, family, colleagues, managers, and fellow business founders to use it, too.
-As a thank you, every time you bring a new user into the platform who directly or indirectly leads to the adoption of a paid annual plan on Expensify, you will earn $250.
+As a thank you, every time you bring a new customer into New Expensify, you'll get $250. Here's how it works.
-# How to get paid for referring people to Expensify
+# How to get paid to refer anyone to New Expensify
-1. Submit a report or invoice, or share your referral link with anyone you know who is spending too much time on expenses, or works at a company that could benefit from using Expensify.
+The sky's the limit for this referral program! Your referral can be anyone - a friend, family member, boss, coworker, neighbor, or even social media follower. We're making it as easy as possible to get that cold hard referral $$$.
-2. You will get $250 for any referred business that commits to an annual subscription, has 2 or more active users, and makes two monthly payments.
+1. There are a bunch of different ways to kick off a referral in New Expensify:
+ - Start a chat
+ - Request money
+ - Send money
+ - @ mention someone
+ - Add them to a workspace
+
+2. You'll get $250 for each referral as long as:
+ - You're the first to refer them to Expensify
+ - They start an annual subscription with two or more active users
+ - They make two payments toward that annual subscription
-That’s right! You can refer anyone working at any company you know.
-
-If their company goes on to become an Expensify customer with an annual subscription, and you are the earliest recorded referrer of a user on that company’s paid Expensify Policy, you'll get paid a referral reward.
-
-The best way to start is to submit any receipt to your manager (you'll get paid back and set yourself up for $250 if they start a subscription: win-win!)
-
-Referral rewards for the Spring/Summer 2023 campaign will be paid by direct deposit.
+For now, referral rewards will be paid via direct deposit into bank accounts that are connected to Expensify.
# FAQ
-- **How will I know if I am the first person to refer a company to Expensify?**
+- **How will I know if I'm the first person to refer a company to Expensify?**
-Successful referrers are notified after their referral pays for 2 months of an annual subscription. We will check for the earliest recorded referrer of a user on the policy, and if that is you, then we will let you know.
+Successful referrers are notified after their referral pays for two months of an annual Expensify subscription. We'll check for the earliest recorded referrer of a member on the workspace, and if that's you, we'll let you know.
- **How will you pay me if I am successful?**
-In the Spring 2023 campaign, Expensify will be paying successful referrers via direct deposit to the Deposit-Only account you have on file. Referral payouts will happen once a month for the duration of the campaign. If you do not have a Deposit-Only account at the time of your referral payout, your deposit will be processed in the next batch.
+For now, Expensify will pay successful referrers via direct deposit to the Deposit-Only bank account you have on file. Referral payouts will happen once a month. If you don't have a Deposit-Only bank account connected to Expensify at the time of your referral payout, your deposit will be processed in the next batch.
-Learn how to add a Deposit-Only account [here](https://community.expensify.com/discussion/4641/how-to-add-a-deposit-only-bank-account-both-personal-and-business).
+Learn how to add a Deposit-Only bank account [here](https://community.expensify.com/discussion/4641/how-to-add-a-deposit-only-bank-account-both-personal-and-business).
- **I’m outside of the US, how do I get paid?**
-While our referral payouts are in USD, you will be able to get paid via a Wise Borderless account. Learn more [here](https://community.expensify.com/discussion/5940/how-to-get-reimbursed-outside-the-us-with-wise-for-non-us-employees).
+While our referral payouts are in USD, you'll be able to get paid via a Wise Borderless account. Learn more [here](https://community.expensify.com/discussion/5940/how-to-get-reimbursed-outside-the-us-with-wise-for-non-us-employees).
- **My referral wasn’t counted! How can I appeal?**
-Expensify reserves the right to modify the terms of the referral program at any time, and pays out referral bonuses for eligible companies at its own discretion.
-
-Please send a message to concierge@expensify.com with the billing owner of the company you have referred and our team will review the referral and get back to you.
-
-- **Where can I find my referral link?**
+Expensify reserves the right to modify the terms of the referral program at any time, and pays out referral bonuses for eligible members at its own discretion. If you think there's been a mistake, please send a message to concierge@expensify.com with the email of your referral and our team will review your case.
-Expensify members who are opted-in for our newsletters will have received an email containing their unique referral link.
+- **Where can I find my referral link?**
-On the mobile app, go to **Settings** > **Invite a Friend** > **Share Invite Link** to retrieve your referral link.
+In New Expensify, go to **Settings** > **Share code** > **Get $250** to retrieve your invite link.
diff --git a/docs/index.html b/docs/index.html
index 70bd5f31545a..ceea63cb398a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -12,9 +12,4 @@
{{ site.data.routes.home.title }}
{% include platform-card.html href=platform.platform_href %}
{% endfor %}
-
-
-
- {% include floating-concierge-button.html id="floating-concierge-button-global" %}
-
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index d7b29e9b9487..1e827cab6935 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageTypeAPPLCFBundleShortVersionString
- 1.4.11
+ 1.4.12CFBundleSignature????CFBundleURLTypes
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.4.11.16
+ 1.4.12.2ITSAppUsesNonExemptEncryptionLSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index eafa6e487154..9e489e59474f 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -15,10 +15,10 @@
CFBundlePackageTypeBNDLCFBundleShortVersionString
- 1.4.11
+ 1.4.12CFBundleSignature????CFBundleVersion
- 1.4.11.16
+ 1.4.12.2
diff --git a/package-lock.json b/package-lock.json
index f11bfa005834..c6c12e491cde 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.4.11-16",
+ "version": "1.4.12-2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.4.11-16",
+ "version": "1.4.12-2",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -35,7 +35,7 @@
"@react-native-google-signin/google-signin": "^10.0.1",
"@react-native-picker/picker": "^2.4.3",
"@react-navigation/material-top-tabs": "^6.6.3",
- "@react-navigation/native": "6.1.6",
+ "@react-navigation/native": "6.1.8",
"@react-navigation/stack": "6.3.16",
"@react-ng/bounds-observer": "^0.2.1",
"@rnmapbox/maps": "^10.0.11",
@@ -8563,16 +8563,16 @@
}
},
"node_modules/@react-navigation/core": {
- "version": "6.4.8",
- "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.8.tgz",
- "integrity": "sha512-klZ9Mcf/P2j+5cHMoGyIeurEzyBM2Uq9+NoSFrF6sdV5iCWHLFhrCXuhbBiQ5wVLCKf4lavlkd/DDs47PXs9RQ==",
+ "version": "6.4.10",
+ "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz",
+ "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==",
"dependencies": {
- "@react-navigation/routers": "^6.1.8",
+ "@react-navigation/routers": "^6.1.9",
"escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.23",
"query-string": "^7.1.3",
"react-is": "^16.13.0",
- "use-latest-callback": "^0.1.5"
+ "use-latest-callback": "^0.1.7"
},
"peerDependencies": {
"react": "*"
@@ -8608,11 +8608,11 @@
}
},
"node_modules/@react-navigation/native": {
- "version": "6.1.6",
- "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.6.tgz",
- "integrity": "sha512-14PmSy4JR8HHEk04QkxQ0ZLuqtiQfb4BV9kkMXD2/jI4TZ+yc43OnO6fQ2o9wm+Bq8pY3DxyerC2AjNUz+oH7Q==",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.8.tgz",
+ "integrity": "sha512-0alti852nV+8oCVm9H80G6kZvrHoy51+rXBvVCRUs2rNDDozC/xPZs8tyeCJkqdw3cpxZDK8ndXF22uWq28+0Q==",
"dependencies": {
- "@react-navigation/core": "^6.4.8",
+ "@react-navigation/core": "^6.4.9",
"escape-string-regexp": "^4.0.0",
"fast-deep-equal": "^3.1.3",
"nanoid": "^3.1.23"
@@ -8623,9 +8623,9 @@
}
},
"node_modules/@react-navigation/routers": {
- "version": "6.1.8",
- "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.8.tgz",
- "integrity": "sha512-CEge+ZLhb1HBrSvv4RwOol7EKLW1QoqVIQlE9TN5MpxS/+VoQvP+cLbuz0Op53/iJfYhtXRFd1ZAd3RTRqto9w==",
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz",
+ "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==",
"dependencies": {
"nanoid": "^3.1.23"
}
@@ -50723,9 +50723,9 @@
}
},
"node_modules/use-latest-callback": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.6.tgz",
- "integrity": "sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg==",
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz",
+ "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==",
"peerDependencies": {
"react": ">=16.8"
}
@@ -58884,16 +58884,16 @@
}
},
"@react-navigation/core": {
- "version": "6.4.8",
- "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.8.tgz",
- "integrity": "sha512-klZ9Mcf/P2j+5cHMoGyIeurEzyBM2Uq9+NoSFrF6sdV5iCWHLFhrCXuhbBiQ5wVLCKf4lavlkd/DDs47PXs9RQ==",
+ "version": "6.4.10",
+ "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz",
+ "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==",
"requires": {
- "@react-navigation/routers": "^6.1.8",
+ "@react-navigation/routers": "^6.1.9",
"escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.23",
"query-string": "^7.1.3",
"react-is": "^16.13.0",
- "use-latest-callback": "^0.1.5"
+ "use-latest-callback": "^0.1.7"
}
},
"@react-navigation/devtools": {
@@ -58915,20 +58915,20 @@
}
},
"@react-navigation/native": {
- "version": "6.1.6",
- "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.6.tgz",
- "integrity": "sha512-14PmSy4JR8HHEk04QkxQ0ZLuqtiQfb4BV9kkMXD2/jI4TZ+yc43OnO6fQ2o9wm+Bq8pY3DxyerC2AjNUz+oH7Q==",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.8.tgz",
+ "integrity": "sha512-0alti852nV+8oCVm9H80G6kZvrHoy51+rXBvVCRUs2rNDDozC/xPZs8tyeCJkqdw3cpxZDK8ndXF22uWq28+0Q==",
"requires": {
- "@react-navigation/core": "^6.4.8",
+ "@react-navigation/core": "^6.4.9",
"escape-string-regexp": "^4.0.0",
"fast-deep-equal": "^3.1.3",
"nanoid": "^3.1.23"
}
},
"@react-navigation/routers": {
- "version": "6.1.8",
- "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.8.tgz",
- "integrity": "sha512-CEge+ZLhb1HBrSvv4RwOol7EKLW1QoqVIQlE9TN5MpxS/+VoQvP+cLbuz0Op53/iJfYhtXRFd1ZAd3RTRqto9w==",
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz",
+ "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==",
"requires": {
"nanoid": "^3.1.23"
}
@@ -89240,9 +89240,9 @@
}
},
"use-latest-callback": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.6.tgz",
- "integrity": "sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg==",
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz",
+ "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==",
"requires": {}
},
"use-memo-one": {
diff --git a/package.json b/package.json
index b18c616f6bb4..dba9988e34e8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.4.11-16",
+ "version": "1.4.12-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.",
@@ -83,7 +83,7 @@
"@react-native-google-signin/google-signin": "^10.0.1",
"@react-native-picker/picker": "^2.4.3",
"@react-navigation/material-top-tabs": "^6.6.3",
- "@react-navigation/native": "6.1.6",
+ "@react-navigation/native": "6.1.8",
"@react-navigation/stack": "6.3.16",
"@react-ng/bounds-observer": "^0.2.1",
"@rnmapbox/maps": "^10.0.11",
diff --git a/patches/@react-navigation+native+6.1.6.patch b/patches/@react-navigation+native+6.1.8.patch
similarity index 90%
rename from patches/@react-navigation+native+6.1.6.patch
rename to patches/@react-navigation+native+6.1.8.patch
index eb933683c850..c461d7e510fe 100644
--- a/patches/@react-navigation+native+6.1.6.patch
+++ b/patches/@react-navigation+native+6.1.8.patch
@@ -133,7 +133,7 @@ index 0000000..16da117
+//# sourceMappingURL=findFocusedRouteKey.js.map
\ No newline at end of file
diff --git a/node_modules/@react-navigation/native/lib/module/useLinking.js b/node_modules/@react-navigation/native/lib/module/useLinking.js
-index 5bf2a88..a4318ef 100644
+index 6f0ac51..a77b608 100644
--- a/node_modules/@react-navigation/native/lib/module/useLinking.js
+++ b/node_modules/@react-navigation/native/lib/module/useLinking.js
@@ -2,6 +2,7 @@ import { findFocusedRoute, getActionFromState as getActionFromStateDefault, getP
@@ -144,37 +144,7 @@ index 5bf2a88..a4318ef 100644
import ServerContext from './ServerContext';
/**
* Find the matching navigation state that changed between 2 navigation states
-@@ -34,32 +35,52 @@ const findMatchingState = (a, b) => {
- /**
- * Run async function in series as it's called.
- */
--const series = cb => {
-- // Whether we're currently handling a callback
-- let handling = false;
-- let queue = [];
-- const callback = async () => {
-- try {
-- if (handling) {
-- // If we're currently handling a previous event, wait before handling this one
-- // Add the callback to the beginning of the queue
-- queue.unshift(callback);
-- return;
-- }
-- handling = true;
-- await cb();
-- } finally {
-- handling = false;
-- if (queue.length) {
-- // If we have queued items, handle the last one
-- const last = queue.pop();
-- last === null || last === void 0 ? void 0 : last();
-- }
-- }
-+const series = (cb) => {
-+ let queue = Promise.resolve();
-+ const callback = () => {
-+ queue = queue.then(cb);
- };
+@@ -42,6 +43,44 @@ export const series = cb => {
return callback;
};
let linkingHandlers = [];
@@ -219,7 +189,7 @@ index 5bf2a88..a4318ef 100644
export default function useLinking(ref, _ref) {
let {
independent,
-@@ -251,6 +272,9 @@ export default function useLinking(ref, _ref) {
+@@ -231,6 +270,9 @@ export default function useLinking(ref, _ref) {
// Otherwise it's likely a change triggered by `popstate`
path !== pendingPath) {
const historyDelta = (focusedState.history ? focusedState.history.length : focusedState.routes.length) - (previousFocusedState.history ? previousFocusedState.history.length : previousFocusedState.routes.length);
@@ -229,7 +199,7 @@ index 5bf2a88..a4318ef 100644
if (historyDelta > 0) {
// If history length is increased, we should pushState
// Note that path might not actually change here, for example, drawer open should pushState
-@@ -262,34 +286,55 @@ export default function useLinking(ref, _ref) {
+@@ -242,34 +284,55 @@ export default function useLinking(ref, _ref) {
// If history length is decreased, i.e. entries were removed, we want to go back
const nextIndex = history.backIndex({
diff --git a/src/App.js b/src/App.js
index e273dcce1e47..12fc6a9426e1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -16,6 +16,9 @@ import {LocaleContextProvider} from './components/LocaleContextProvider';
import OnyxProvider from './components/OnyxProvider';
import PopoverContextProvider from './components/PopoverProvider';
import SafeArea from './components/SafeArea';
+import ThemeIllustrationsProvider from './components/ThemeIllustrationsProvider';
+import ThemeProvider from './components/ThemeProvider';
+import ThemeStylesProvider from './components/ThemeStylesProvider';
import {CurrentReportIDContextProvider} from './components/withCurrentReportID';
import {EnvironmentProvider} from './components/withEnvironment';
import {KeyboardStateProvider} from './components/withKeyboardState';
@@ -26,9 +29,6 @@ import OnyxUpdateManager from './libs/actions/OnyxUpdateManager';
import * as Session from './libs/actions/Session';
import * as Environment from './libs/Environment/Environment';
import {ReportAttachmentsProvider} from './pages/home/report/ReportAttachmentsContext';
-import ThemeIllustrationsProvider from './styles/illustrations/ThemeIllustrationsProvider';
-import ThemeProvider from './styles/themes/ThemeProvider';
-import ThemeStylesProvider from './styles/ThemeStylesProvider';
// For easier debugging and development, when we are in web we expose Onyx to the window, so you can more easily set data into Onyx
if (window && Environment.isDevelopment()) {
diff --git a/src/CONST.ts b/src/CONST.ts
index d4208d51a78c..c0e3d64b5eee 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -255,6 +255,7 @@ const CONST = {
BETA_COMMENT_LINKING: 'commentLinking',
POLICY_ROOMS: 'policyRooms',
VIOLATIONS: 'violations',
+ REPORT_FIELDS: 'reportFields',
},
BUTTON_STATES: {
DEFAULT: 'default',
@@ -706,9 +707,10 @@ const CONST = {
DEFAULT: 'default',
},
THEME: {
- DEFAULT: 'dark',
- LIGHT: 'light',
+ DEFAULT: 'system',
+ FALLBACK: 'dark',
DARK: 'dark',
+ LIGHT: 'light',
SYSTEM: 'system',
},
COLOR_SCHEME: {
@@ -1099,11 +1101,6 @@ const CONST = {
USER_CANCELLED: 'User canceled flow.',
USER_TAPPED_BACK: 'User exited by clicking the back button.',
USER_EXITED: 'User exited by manual action.',
- USER_CAMERA_DENINED: 'Onfido.OnfidoFlowError',
- USER_CAMERA_PERMISSION: 'Encountered an error: cameraPermission',
- // eslint-disable-next-line max-len
- USER_CAMERA_CONSENT_DENIED:
- 'Unexpected result Intent. It might be a result of incorrect integration, make sure you only pass Onfido intent to handleActivityResult. It might be due to unpredictable crash or error. Please report the problem to android-sdk@onfido.com. Intent: null \n resultCode: 0',
},
},
@@ -2731,17 +2728,125 @@ const CONST = {
EXPENSIFY_LOGO_SIZE_RATIO: 0.22,
EXPENSIFY_LOGO_MARGIN_RATIO: 0.03,
},
+ /**
+ * Acceptable values for the `accessibilityRole` prop on react native components.
+ *
+ * **IMPORTANT:** Do not use with the `role` prop as it can cause errors.
+ *
+ * @deprecated ACCESSIBILITY_ROLE is deprecated. Please use CONST.ROLE instead.
+ */
ACCESSIBILITY_ROLE: {
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
BUTTON: 'button',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
LINK: 'link',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
MENUITEM: 'menuitem',
- TEXT: 'presentation',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ TEXT: 'text',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
RADIO: 'radio',
- IMAGEBUTTON: 'img button',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ IMAGEBUTTON: 'imagebutton',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
CHECKBOX: 'checkbox',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
SWITCH: 'switch',
- ADJUSTABLE: 'slider',
- IMAGE: 'img',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ ADJUSTABLE: 'adjustable',
+
+ /**
+ * @deprecated Please stop using the accessibilityRole prop and use the role prop instead.
+ */
+ IMAGE: 'image',
+ },
+ /**
+ * Acceptable values for the `role` attribute on react native components.
+ *
+ * **IMPORTANT:** Not for use with the `accessibilityRole` prop, as it accepts different values, and new components
+ * should use the `role` prop instead.
+ */
+ ROLE: {
+ /** Use for elements with important, time-sensitive information. */
+ ALERT: 'alert',
+ /** Use for elements that act as buttons. */
+ BUTTON: 'button',
+ /** Use for elements representing checkboxes. */
+ CHECKBOX: 'checkbox',
+ /** Use for elements that allow a choice from multiple options. */
+ COMBOBOX: 'combobox',
+ /** Use with scrollable lists to represent a grid layout. */
+ GRID: 'grid',
+ /** Use for section headers or titles. */
+ HEADING: 'heading',
+ /** Use for image elements. */
+ IMG: 'img',
+ /** Use for elements that navigate to other pages or content. */
+ LINK: 'link',
+ /** Use to identify a list of items. */
+ LIST: 'list',
+ /** Use for a list of choices or options. */
+ MENU: 'menu',
+ /** Use for a container of multiple menus. */
+ MENUBAR: 'menubar',
+ /** Use for items within a menu. */
+ MENUITEM: 'menuitem',
+ /** Use when no specific role is needed. */
+ NONE: 'none',
+ /** Use for elements that don't require a specific role. */
+ PRESENTATION: 'presentation',
+ /** Use for elements showing progress of a task. */
+ PROGRESSBAR: 'progressbar',
+ /** Use for radio buttons. */
+ RADIO: 'radio',
+ /** Use for groups of radio buttons. */
+ RADIOGROUP: 'radiogroup',
+ /** Use for scrollbar elements. */
+ SCROLLBAR: 'scrollbar',
+ /** Use for text fields that are used for searching. */
+ SEARCHBOX: 'searchbox',
+ /** Use for adjustable elements like sliders. */
+ SLIDER: 'slider',
+ /** Use for a button that opens a list of choices. */
+ SPINBUTTON: 'spinbutton',
+ /** Use for elements providing a summary of app conditions. */
+ SUMMARY: 'summary',
+ /** Use for on/off switch elements. */
+ SWITCH: 'switch',
+ /** Use for tab elements in a tab list. */
+ TAB: 'tab',
+ /** Use for a list of tabs. */
+ TABLIST: 'tablist',
+ /** Use for timer elements. */
+ TIMER: 'timer',
+ /** Use for toolbars containing action buttons or components. */
+ TOOLBAR: 'toolbar',
},
TRANSLATION_KEYS: {
ATTACHMENT: 'common.attachment',
@@ -2799,6 +2904,10 @@ const CONST = {
NAVIGATE: 'NAVIGATE',
},
},
+ TIME_PERIOD: {
+ AM: 'AM',
+ PM: 'PM',
+ },
INDENTS: ' ',
PARENT_CHILD_SEPARATOR: ': ',
CATEGORY_LIST_THRESHOLD: 8,
@@ -2808,7 +2917,7 @@ const CONST = {
SBE: 'SbeDemoSetup',
MONEY2020: 'Money2020DemoSetup',
},
-
+ COLON: ':',
MAPBOX: {
PADDING: 50,
DEFAULT_ZOOM: 10,
@@ -2854,7 +2963,7 @@ const CONST = {
SHARE_CODE: 'shareCode',
},
REVENUE: 250,
- LEARN_MORE_LINK: 'https://help.expensify.com/articles/new-expensify/billing-and-plan-types/Referral-Program',
+ LEARN_MORE_LINK: 'https://help.expensify.com/articles/new-expensify/get-paid-back/Referral-Program',
LINK: 'https://join.my.expensify.com',
},
diff --git a/src/Expensify.js b/src/Expensify.js
index aece93c0ff4d..756df5b79b88 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -112,6 +112,7 @@ function Expensify(props) {
}, [props.isCheckingPublicRoom]);
const isAuthenticated = useMemo(() => Boolean(lodashGet(props.session, 'authToken', null)), [props.session]);
+ const autoAuthState = useMemo(() => lodashGet(props.session, 'autoAuthState', ''), [props.session]);
const contextValue = useMemo(
() => ({
@@ -207,7 +208,10 @@ function Expensify(props) {
}
return (
-
+
{shouldInit && (
<>
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index a268c008cee8..0cc7934ad007 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -334,10 +334,10 @@ const ONYXKEYS = {
WAYPOINT_FORM_DRAFT: 'waypointFormDraft',
SETTINGS_STATUS_SET_FORM: 'settingsStatusSetForm',
SETTINGS_STATUS_SET_FORM_DRAFT: 'settingsStatusSetFormDraft',
- SETTINGS_STATUS_CLEAR_AFTER_FORM: 'settingsStatusClearAfterForm',
- SETTINGS_STATUS_CLEAR_AFTER_FORM_DRAFT: 'settingsStatusClearAfterFormDraft',
SETTINGS_STATUS_SET_CLEAR_AFTER_FORM: 'settingsStatusSetClearAfterForm',
SETTINGS_STATUS_SET_CLEAR_AFTER_FORM_DRAFT: 'settingsStatusSetClearAfterFormDraft',
+ SETTINGS_STATUS_CLEAR_DATE_FORM: 'settingsStatusClearDateForm',
+ SETTINGS_STATUS_CLEAR_DATE_FORM_DRAFT: 'settingsStatusClearDateFormDraft',
PRIVATE_NOTES_FORM: 'privateNotesForm',
PRIVATE_NOTES_FORM_DRAFT: 'privateNotesFormDraft',
I_KNOW_A_TEACHER_FORM: 'iKnowTeacherForm',
@@ -383,7 +383,7 @@ type OnyxValues = {
[ONYXKEYS.COUNTRY]: string;
[ONYXKEYS.USER]: OnyxTypes.User;
[ONYXKEYS.USER_LOCATION]: OnyxTypes.UserLocation;
- [ONYXKEYS.LOGIN_LIST]: Record;
+ [ONYXKEYS.LOGIN_LIST]: OnyxTypes.LoginList;
[ONYXKEYS.SESSION]: OnyxTypes.Session;
[ONYXKEYS.BETAS]: OnyxTypes.Beta[];
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf;
@@ -403,8 +403,8 @@ type OnyxValues = {
[ONYXKEYS.WALLET_ONFIDO]: OnyxTypes.WalletOnfido;
[ONYXKEYS.WALLET_ADDITIONAL_DETAILS]: OnyxTypes.WalletAdditionalDetails;
[ONYXKEYS.WALLET_TERMS]: OnyxTypes.WalletTerms;
- [ONYXKEYS.BANK_ACCOUNT_LIST]: Record;
- [ONYXKEYS.FUND_LIST]: Record;
+ [ONYXKEYS.BANK_ACCOUNT_LIST]: OnyxTypes.BankAccountList;
+ [ONYXKEYS.FUND_LIST]: OnyxTypes.FundList;
[ONYXKEYS.CARD_LIST]: Record;
[ONYXKEYS.WALLET_STATEMENT]: OnyxTypes.WalletStatement;
[ONYXKEYS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount;
@@ -440,7 +440,7 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy;
[ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory;
[ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags;
- [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMember;
+ [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories;
[ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers;
@@ -508,8 +508,8 @@ type OnyxValues = {
[ONYXKEYS.FORMS.WAYPOINT_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.SETTINGS_STATUS_SET_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.SETTINGS_STATUS_SET_FORM_DRAFT]: OnyxTypes.Form;
- [ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_AFTER_FORM]: OnyxTypes.Form;
- [ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_AFTER_FORM_DRAFT]: OnyxTypes.Form;
+ [ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_DATE_FORM]: OnyxTypes.Form;
+ [ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_DATE_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.SETTINGS_STATUS_SET_CLEAR_AFTER_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.SETTINGS_STATUS_SET_CLEAR_AFTER_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.PRIVATE_NOTES_FORM]: OnyxTypes.Form;
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 53763d6d7cd1..ca1fe9f0e81a 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -34,7 +34,7 @@ const ROUTES = {
VALIDATE_LOGIN: 'v/:accountID/:validateCode',
GET_ASSISTANCE: {
route: 'get-assistance/:taskID',
- getRoute: (taskID: string) => `get-assistance/${taskID}` as const,
+ getRoute: (taskID: string, backTo: string) => getUrlWithBackToParam(`get-assistance/${taskID}`, backTo),
},
UNLINK_LOGIN: 'u/:accountID/:validateCode',
APPLE_SIGN_IN: 'sign-in-with-apple',
@@ -140,7 +140,9 @@ const ROUTES = {
getRoute: (backTo?: string) => getUrlWithBackToParam('settings/security/two-factor-auth', backTo),
},
SETTINGS_STATUS: 'settings/profile/status',
- SETTINGS_STATUS_SET: 'settings/profile/status/set',
+ SETTINGS_STATUS_CLEAR_AFTER: 'settings/profile/status/clear-after',
+ SETTINGS_STATUS_CLEAR_AFTER_DATE: 'settings/profile/status/clear-after/date',
+ SETTINGS_STATUS_CLEAR_AFTER_TIME: 'settings/profile/status/clear-after/time',
KEYBOARD_SHORTCUTS: 'keyboard-shortcuts',
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 921f57953482..2cd263237866 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -37,8 +37,10 @@ const SCREENS = {
CONTACT_METHODS: 'Settings_ContactMethods',
CONTACT_METHOD_DETAILS: 'Settings_ContactMethodDetails',
NEW_CONTACT_METHOD: 'Settings_NewContactMethod',
+ STATUS_CLEAR_AFTER: 'Settings_Status_Clear_After',
+ STATUS_CLEAR_AFTER_DATE: 'Settings_Status_Clear_After_Date',
+ STATUS_CLEAR_AFTER_TIME: 'Settings_Status_Clear_After_Time',
STATUS: 'Settings_Status',
- STATUS_SET: 'Settings_Status_Set',
PRONOUNS: 'Settings_Pronouns',
TIMEZONE: 'Settings_Timezone',
TIMEZONE_SELECT: 'Settings_Timezone_Select',
diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js
index 68d529c4a78d..6e3d0e2f0d68 100644
--- a/src/components/AddPlaidBankAccount.js
+++ b/src/components/AddPlaidBankAccount.js
@@ -6,11 +6,11 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import KeyboardShortcut from '@libs/KeyboardShortcut';
import Log from '@libs/Log';
import {plaidDataPropTypes} from '@pages/ReimbursementAccount/plaidDataPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as App from '@userActions/App';
import * as BankAccounts from '@userActions/BankAccounts';
import CONST from '@src/CONST';
diff --git a/src/components/AddressForm.js b/src/components/AddressForm.js
index 1621328d388f..68d451e5c7c8 100644
--- a/src/components/AddressForm.js
+++ b/src/components/AddressForm.js
@@ -5,9 +5,9 @@ import React, {useCallback} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import AddressSearch from './AddressSearch';
import CountrySelector from './CountrySelector';
diff --git a/src/components/AddressSearch/CurrentLocationButton.js b/src/components/AddressSearch/CurrentLocationButton.js
index 90d2c15733f1..06541565f567 100644
--- a/src/components/AddressSearch/CurrentLocationButton.js
+++ b/src/components/AddressSearch/CurrentLocationButton.js
@@ -5,10 +5,10 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import getButtonState from '@libs/getButtonState';
-import colors from '@styles/colors';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import colors from '@styles/theme/colors';
const propTypes = {
/** Callback that runs when location button is clicked */
diff --git a/src/components/AddressSearch/index.js b/src/components/AddressSearch/index.js
index 2fed1d153947..3c764b36f3eb 100644
--- a/src/components/AddressSearch/index.js
+++ b/src/components/AddressSearch/index.js
@@ -10,13 +10,13 @@ import networkPropTypes from '@components/networkPropTypes';
import {withNetwork} from '@components/OnyxProvider';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ApiUtils from '@libs/ApiUtils';
import compose from '@libs/compose';
import getCurrentPosition from '@libs/getCurrentPosition';
import * as GooglePlacesUtils from '@libs/GooglePlacesUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import CurrentLocationButton from './CurrentLocationButton';
diff --git a/src/components/AmountTextInput.js b/src/components/AmountTextInput.js
index bd88712432a8..25e1ce6f05ec 100644
--- a/src/components/AmountTextInput.js
+++ b/src/components/AmountTextInput.js
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import refPropTypes from './refPropTypes';
import TextInput from './TextInput';
@@ -27,6 +28,12 @@ const propTypes = {
/** Function to call when selection in text input is changed */
onSelectionChange: PropTypes.func,
+ /** Style for the input */
+ style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
+
+ /** Style for the container */
+ containerStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
+
/** Function to call to handle key presses in the text input */
onKeyPress: PropTypes.func,
};
@@ -36,16 +43,19 @@ const defaultProps = {
selection: undefined,
onSelectionChange: () => {},
onKeyPress: () => {},
+ style: {},
+ containerStyles: {},
};
function AmountTextInput(props) {
const styles = useThemeStyles();
+ const StyleUtils = useStyleUtils();
return (
);
}
diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
index 1e2d18bc4691..6161ba140726 100644
--- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
+++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.js
@@ -58,7 +58,7 @@ function BaseAnchorForAttachmentsOnly(props) {
onPressOut={props.onPressOut}
onLongPress={(event) => showContextMenuForReport(event, anchor, report.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))}
accessibilityLabel={fileName}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
(linkRef = el)}
style={StyleSheet.flatten([style, defaultTextStyle])}
- role={CONST.ACCESSIBILITY_ROLE.LINK}
+ role={CONST.ROLE.LINK}
hrefAttrs={{
rel,
target: isEmail || !linkProps.href ? '_self' : target,
diff --git a/src/components/AnimatedStep/index.tsx b/src/components/AnimatedStep/index.tsx
index 1a87592cba9b..e2b9952c0617 100644
--- a/src/components/AnimatedStep/index.tsx
+++ b/src/components/AnimatedStep/index.tsx
@@ -1,8 +1,8 @@
import React, {useMemo} from 'react';
import {StyleProp, ViewStyle} from 'react-native';
import * as Animatable from 'react-native-animatable';
+import useThemeStyles from '@hooks/useThemeStyles';
import useNativeDriver from '@libs/useNativeDriver';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import {AnimationDirection} from './AnimatedStepContext';
diff --git a/src/components/AnonymousReportFooter.tsx b/src/components/AnonymousReportFooter.tsx
index 65dc813a829d..877ca9444661 100644
--- a/src/components/AnonymousReportFooter.tsx
+++ b/src/components/AnonymousReportFooter.tsx
@@ -3,7 +3,7 @@ import {Text, View} from 'react-native';
import {OnyxCollection} from 'react-native-onyx';
import {OnyxEntry} from 'react-native-onyx/lib/types';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@userActions/Session';
import {PersonalDetails, Report} from '@src/types/onyx';
import AvatarWithDisplayName from './AvatarWithDisplayName';
diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx
index 712ef6be769e..7dadd86debfe 100644
--- a/src/components/ArchivedReportFooter.tsx
+++ b/src/components/ArchivedReportFooter.tsx
@@ -2,10 +2,10 @@ import lodashEscape from 'lodash/escape';
import React from 'react';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetailsList, Report, ReportAction} from '@src/types/onyx';
diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js
index 79be536945ac..13b3b9f1e836 100755
--- a/src/components/AttachmentModal.js
+++ b/src/components/AttachmentModal.js
@@ -8,6 +8,9 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL';
import compose from '@libs/compose';
@@ -19,9 +22,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import useNativeDriver from '@libs/useNativeDriver';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/AttachmentPicker/index.native.js b/src/components/AttachmentPicker/index.native.js
index 5b955ee69dd3..59928b80c4b1 100644
--- a/src/components/AttachmentPicker/index.native.js
+++ b/src/components/AttachmentPicker/index.native.js
@@ -12,9 +12,9 @@ import Popover from '@components/Popover';
import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as FileUtils from '@libs/fileDownload/FileUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {defaultProps as baseDefaultProps, propTypes as basePropTypes} from './attachmentPickerPropTypes';
import launchCamera from './launchCamera';
diff --git a/src/components/Attachments/AttachmentCarousel/AttachmentCarouselCellRenderer.js b/src/components/Attachments/AttachmentCarousel/AttachmentCarouselCellRenderer.js
index dd2713a38b2b..f4cbffc0e1e4 100644
--- a/src/components/Attachments/AttachmentCarousel/AttachmentCarouselCellRenderer.js
+++ b/src/components/Attachments/AttachmentCarousel/AttachmentCarouselCellRenderer.js
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
import {PixelRatio, View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** Cell Container styles */
diff --git a/src/components/Attachments/AttachmentCarousel/CarouselButtons.js b/src/components/Attachments/AttachmentCarousel/CarouselButtons.js
index 14a6ea268468..1847d30ede22 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselButtons.js
+++ b/src/components/Attachments/AttachmentCarousel/CarouselButtons.js
@@ -7,9 +7,9 @@ import Button from '@components/Button';
import * as Expensicons from '@components/Icon/Expensicons';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** Where the arrows should be visible */
diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
index fbc49590d5ae..e1fcc86e12a5 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js
+++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
@@ -8,8 +8,8 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed
import SafeAreaConsumer from '@components/SafeAreaConsumer';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import ReportAttachmentsContext from '@pages/home/report/ReportAttachmentsContext';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -81,7 +81,7 @@ function CarouselItem({item, isFocused, onPress}) {
{children}
diff --git a/src/components/Attachments/AttachmentCarousel/Pager/ImageTransformer.js b/src/components/Attachments/AttachmentCarousel/Pager/ImageTransformer.js
index cc1e20cb44e0..4bce03b6f25e 100644
--- a/src/components/Attachments/AttachmentCarousel/Pager/ImageTransformer.js
+++ b/src/components/Attachments/AttachmentCarousel/Pager/ImageTransformer.js
@@ -15,7 +15,7 @@ import Animated, {
withDecay,
withSpring,
} from 'react-native-reanimated';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import AttachmentCarouselPagerContext from './AttachmentCarouselPagerContext';
import ImageWrapper from './ImageWrapper';
diff --git a/src/components/Attachments/AttachmentCarousel/Pager/ImageWrapper.js b/src/components/Attachments/AttachmentCarousel/Pager/ImageWrapper.js
index b0a8b1f0d083..b639eb291bb1 100644
--- a/src/components/Attachments/AttachmentCarousel/Pager/ImageWrapper.js
+++ b/src/components/Attachments/AttachmentCarousel/Pager/ImageWrapper.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {StyleSheet} from 'react-native';
import Animated from 'react-native-reanimated';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
const imageWrapperPropTypes = {
children: PropTypes.node.isRequired,
diff --git a/src/components/Attachments/AttachmentCarousel/Pager/index.js b/src/components/Attachments/AttachmentCarousel/Pager/index.js
index 6913941ed726..15c98ece62cb 100644
--- a/src/components/Attachments/AttachmentCarousel/Pager/index.js
+++ b/src/components/Attachments/AttachmentCarousel/Pager/index.js
@@ -6,7 +6,7 @@ import PagerView from 'react-native-pager-view';
import Animated, {runOnJS, useAnimatedProps, useAnimatedReaction, useEvent, useHandler, useSharedValue} from 'react-native-reanimated';
import _ from 'underscore';
import refPropTypes from '@components/refPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import AttachmentCarouselPagerContext from './AttachmentCarouselPagerContext';
const AnimatedPagerView = Animated.createAnimatedComponent(createNativeWrapper(PagerView));
diff --git a/src/components/Attachments/AttachmentCarousel/index.js b/src/components/Attachments/AttachmentCarousel/index.js
index fb31e32de91c..8f225d426dca 100644
--- a/src/components/Attachments/AttachmentCarousel/index.js
+++ b/src/components/Attachments/AttachmentCarousel/index.js
@@ -6,10 +6,10 @@ import BlockingView from '@components/BlockingViews/BlockingView';
import * as Illustrations from '@components/Icon/Illustrations';
import withLocalize from '@components/withLocalize';
import withWindowDimensions from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/Attachments/AttachmentCarousel/index.native.js b/src/components/Attachments/AttachmentCarousel/index.native.js
index ea45509d6ce3..374b2d47d12d 100644
--- a/src/components/Attachments/AttachmentCarousel/index.native.js
+++ b/src/components/Attachments/AttachmentCarousel/index.native.js
@@ -5,9 +5,9 @@ import _ from 'underscore';
import BlockingView from '@components/BlockingViews/BlockingView';
import * as Illustrations from '@components/Icon/Illustrations';
import withLocalize from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import ONYXKEYS from '@src/ONYXKEYS';
import {defaultProps, propTypes} from './attachmentCarouselPropTypes';
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
index 22bcf259ed77..78b69be077aa 100755
--- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
@@ -2,8 +2,8 @@ import React, {memo} from 'react';
import ImageView from '@components/ImageView';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {attachmentViewImageDefaultProps, attachmentViewImagePropTypes} from './propTypes';
@@ -28,7 +28,7 @@ function AttachmentViewImage({source, file, isAuthTokenRequired, loadComplete, o
onPress={onPress}
disabled={loadComplete}
style={[styles.flex1, styles.flexRow, styles.alignSelfStretch]}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={file.name || translate('attachmentView.unknownFilename')}
>
{children}
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
index fc443e5ea17b..fd709c82a2e2 100755
--- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.native.js
@@ -3,8 +3,8 @@ import AttachmentCarouselPage from '@components/Attachments/AttachmentCarousel/P
import ImageView from '@components/ImageView';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {attachmentViewImageDefaultProps, attachmentViewImagePropTypes} from './propTypes';
@@ -36,7 +36,7 @@ function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, isUs
onPress={onPress}
disabled={loadComplete}
style={[styles.flex1, styles.flexRow, styles.alignSelfStretch]}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={file.name || translate('attachmentView.unknownFilename')}
>
{children}
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewPdf/index.android.js b/src/components/Attachments/AttachmentView/AttachmentViewPdf/index.android.js
index b9dd65e2716b..308d3cf2c0ba 100644
--- a/src/components/Attachments/AttachmentView/AttachmentViewPdf/index.android.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewPdf/index.android.js
@@ -3,7 +3,7 @@ import {StyleSheet, View} from 'react-native';
import {Gesture, GestureDetector} from 'react-native-gesture-handler';
import Animated, {useSharedValue} from 'react-native-reanimated';
import AttachmentCarouselPagerContext from '@components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import BaseAttachmentViewPdf from './BaseAttachmentViewPdf';
import {attachmentViewPdfDefaultProps, attachmentViewPdfPropTypes} from './propTypes';
diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js
index 6e1ed651ae06..79d1b6f407b9 100755
--- a/src/components/Attachments/AttachmentView/index.js
+++ b/src/components/Attachments/AttachmentView/index.js
@@ -12,13 +12,12 @@ import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL';
import compose from '@libs/compose';
import * as TransactionUtils from '@libs/TransactionUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
-import cursor from '@styles/utilities/cursor';
import variables from '@styles/variables';
import ONYXKEYS from '@src/ONYXKEYS';
import AttachmentViewImage from './AttachmentViewImage';
@@ -141,7 +140,7 @@ function AttachmentView({
onScaleChanged={onScaleChanged}
onToggleKeyboard={onToggleKeyboard}
onLoadComplete={() => !loadComplete && setLoadComplete(true)}
- errorLabelStyles={isUsedInAttachmentModal ? [styles.textLabel, styles.textLarge] : [cursor.cursorAuto]}
+ errorLabelStyles={isUsedInAttachmentModal ? [styles.textLabel, styles.textLarge] : [styles.cursorAuto]}
style={isUsedInAttachmentModal ? styles.imageModalPDF : styles.flex1}
/>
diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
index 07db455968a3..4ad3d45544b0 100644
--- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
+++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx
@@ -5,8 +5,8 @@ import {View} from 'react-native';
import {ScrollView} from 'react-native-gesture-handler';
import Animated, {Easing, FadeOutDown, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import viewForwardedRef from '@src/types/utils/viewForwardedRef';
import type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps} from './types';
diff --git a/src/components/AutoCompleteSuggestions/index.tsx b/src/components/AutoCompleteSuggestions/index.tsx
index 3ccbb4efaf5a..baca4011a177 100644
--- a/src/components/AutoCompleteSuggestions/index.tsx
+++ b/src/components/AutoCompleteSuggestions/index.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {View} from 'react-native';
+import useStyleUtils from '@hooks/useStyleUtils';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
-import useStyleUtils from '@styles/useStyleUtils';
import BaseAutoCompleteSuggestions from './BaseAutoCompleteSuggestions';
import type {AutoCompleteSuggestionsProps} from './types';
diff --git a/src/components/AutoEmailLink.js b/src/components/AutoEmailLink.js
index bffd2493aa5d..af581525ab69 100644
--- a/src/components/AutoEmailLink.js
+++ b/src/components/AutoEmailLink.js
@@ -2,7 +2,7 @@ import {CONST} from 'expensify-common/lib/CONST';
import PropTypes from 'prop-types';
import React from 'react';
import _ from 'underscore';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Text from './Text';
import TextLink from './TextLink';
diff --git a/src/components/AutoUpdateTime.tsx b/src/components/AutoUpdateTime.tsx
index 7b584e236b37..258bdb281eb2 100644
--- a/src/components/AutoUpdateTime.tsx
+++ b/src/components/AutoUpdateTime.tsx
@@ -4,8 +4,8 @@
*/
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import {Timezone} from '@src/types/onyx/PersonalDetails';
import Text from './Text';
import withLocalize, {WithLocalizeProps} from './withLocalize';
diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx
index f801cb11e9df..978d2f097cbf 100644
--- a/src/components/Avatar.tsx
+++ b/src/components/Avatar.tsx
@@ -1,11 +1,11 @@
import React, {useEffect, useState} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportUtils from '@libs/ReportUtils';
import {AvatarSource} from '@libs/UserUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import type {AvatarSizeName} from '@styles/utils';
import CONST from '@src/CONST';
import {AvatarType} from '@src/types/onyx/OnyxCommon';
diff --git a/src/components/AvatarCropModal/AvatarCropModal.js b/src/components/AvatarCropModal/AvatarCropModal.js
index dcb0470c5ee5..a39daeb78ba7 100644
--- a/src/components/AvatarCropModal/AvatarCropModal.js
+++ b/src/components/AvatarCropModal/AvatarCropModal.js
@@ -15,11 +15,11 @@ import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import cropOrRotateImage from '@libs/cropOrRotateImage';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ImageCropView from './ImageCropView';
import Slider from './Slider';
@@ -413,7 +413,7 @@ function AvatarCropModal(props) {
onLayout={initializeSliderContainer}
onPressIn={(e) => runOnUI(sliderOnPress)(e.nativeEvent.locationX)}
accessibilityLabel="slider"
- role={CONST.ACCESSIBILITY_ROLE.ADJUSTABLE}
+ role={CONST.ROLE.SLIDER}
>
{shouldShowSubscriptAvatar ? (
ReportUtils.navigateToDetailsPage(report)}
style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}
accessibilityLabel={title}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{headerView}
diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js
index eabcd3aa85c5..325d4706da71 100644
--- a/src/components/AvatarWithImagePicker.js
+++ b/src/components/AvatarWithImagePicker.js
@@ -4,12 +4,12 @@ import React, {useEffect, useRef, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import * as FileUtils from '@libs/fileDownload/FileUtils';
import getImageResolution from '@libs/fileDownload/getImageResolution';
import stylePropTypes from '@styles/stylePropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import AttachmentModal from './AttachmentModal';
@@ -297,7 +297,7 @@ function AvatarWithImagePicker({
setIsMenuVisible((prev) => !prev)}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={translate('avatarWithImagePicker.editImage')}
disabled={isAvatarCropModalOpen}
ref={anchorRef}
diff --git a/src/components/AvatarWithIndicator.tsx b/src/components/AvatarWithIndicator.tsx
index 3ae9507350c8..2fd733d4b072 100644
--- a/src/components/AvatarWithIndicator.tsx
+++ b/src/components/AvatarWithIndicator.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as UserUtils from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import Avatar from './Avatar';
import AvatarSkeleton from './AvatarSkeleton';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx
index 82212c66db04..70aebc30ee83 100644
--- a/src/components/Badge.tsx
+++ b/src/components/Badge.tsx
@@ -1,7 +1,7 @@
import React, {useCallback} from 'react';
import {GestureResponderEvent, PressableStateCallbackType, StyleProp, TextStyle, View, ViewStyle} from 'react-native';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import Text from './Text';
@@ -47,7 +47,7 @@ function Badge({success = false, error = false, pressable = false, text, environ
diff --git a/src/components/BaseMiniContextMenuItem.tsx b/src/components/BaseMiniContextMenuItem.tsx
index 082c0e20801a..8d115a37cba7 100644
--- a/src/components/BaseMiniContextMenuItem.tsx
+++ b/src/components/BaseMiniContextMenuItem.tsx
@@ -1,10 +1,10 @@
import React, {ForwardedRef} from 'react';
import {PressableStateCallbackType, View} from 'react-native';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import DomUtils from '@libs/DomUtils';
import getButtonState from '@libs/getButtonState';
import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import Tooltip from './Tooltip/PopoverAnchorTooltip';
diff --git a/src/components/BigNumberPad.tsx b/src/components/BigNumberPad.tsx
index 812e9e78635b..8b840f9d1b57 100644
--- a/src/components/BigNumberPad.tsx
+++ b/src/components/BigNumberPad.tsx
@@ -1,9 +1,9 @@
import React, {useState} from 'react';
import {View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import ControlSelection from '@libs/ControlSelection';
-import useThemeStyles from '@styles/useThemeStyles';
import Button from './Button';
type BigNumberPadProps = {
@@ -15,6 +15,9 @@ type BigNumberPadProps = {
/** Used to locate this view from native classes. */
id?: string;
+
+ /** Whether long press is disabled */
+ isLongPressDisabled: boolean;
};
const padNumbers = [
@@ -24,7 +27,7 @@ const padNumbers = [
['.', '0', '<'],
] as const;
-function BigNumberPad({numberPressed, longPressHandlerStateChanged = () => {}, id = 'numPadView'}: BigNumberPadProps) {
+function BigNumberPad({numberPressed, longPressHandlerStateChanged = () => {}, id = 'numPadView', isLongPressDisabled = false}: BigNumberPadProps) {
const {toLocaleDigit} = useLocalize();
const styles = useThemeStyles();
@@ -85,6 +88,7 @@ function BigNumberPad({numberPressed, longPressHandlerStateChanged = () => {}, i
onMouseDown={(e) => {
e.preventDefault();
}}
+ isLongPressDisabled={isLongPressDisabled}
/>
);
})}
diff --git a/src/components/BlockingViews/BlockingView.js b/src/components/BlockingViews/BlockingView.js
index aec414cdeb74..44f6b7100509 100644
--- a/src/components/BlockingViews/BlockingView.js
+++ b/src/components/BlockingViews/BlockingView.js
@@ -6,9 +6,9 @@ import Icon from '@components/Icon';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/components/BlockingViews/FullPageNotFoundView.js b/src/components/BlockingViews/FullPageNotFoundView.js
index b82474aa0694..ce76b96c0eb0 100644
--- a/src/components/BlockingViews/FullPageNotFoundView.js
+++ b/src/components/BlockingViews/FullPageNotFoundView.js
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import ROUTES from '@src/ROUTES';
import BlockingView from './BlockingView';
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index 9cbd19e03dc7..af8ec33683de 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -9,9 +9,9 @@ import Text from '@components/Text';
import withNavigationFallback from '@components/withNavigationFallback';
import useActiveElement from '@hooks/useActiveElement';
import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import HapticFeedback from '@libs/HapticFeedback';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import validateSubmitShortcut from './validateSubmitShortcut';
@@ -106,6 +106,9 @@ type ButtonProps = (ButtonWithText | ChildrenProps) & {
/** Should enable the haptic feedback? */
shouldEnableHapticFeedback?: boolean;
+ /** Should disable the long press? */
+ isLongPressDisabled?: boolean;
+
/** Id to use for this button */
id?: string;
@@ -149,6 +152,7 @@ function Button(
shouldRemoveRightBorderRadius = false,
shouldRemoveLeftBorderRadius = false,
shouldEnableHapticFeedback = false,
+ isLongPressDisabled = false,
id = '',
accessibilityLabel = '',
@@ -255,6 +259,9 @@ function Button(
return onPress(event);
}}
onLongPress={(event) => {
+ if (isLongPressDisabled) {
+ return;
+ }
if (shouldEnableHapticFeedback) {
HapticFeedback.longPress();
}
@@ -293,7 +300,7 @@ function Button(
]}
id={id}
accessibilityLabel={accessibilityLabel}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
hoverDimmingValue={1}
>
{renderContent()}
diff --git a/src/components/ButtonWithDropdownMenu.js b/src/components/ButtonWithDropdownMenu.js
index a5f311740f19..0291143a9dbc 100644
--- a/src/components/ButtonWithDropdownMenu.js
+++ b/src/components/ButtonWithDropdownMenu.js
@@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
import React, {useEffect, useRef, useState} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import Button from './Button';
import Icon from './Icon';
diff --git a/src/components/CardPreview.tsx b/src/components/CardPreview.tsx
index 6dc8abfb80ef..e3ddbd54b892 100644
--- a/src/components/CardPreview.tsx
+++ b/src/components/CardPreview.tsx
@@ -3,7 +3,7 @@ import {View} from 'react-native';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
import ExpensifyCardImage from '@assets/images/expensify-card.svg';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import ONYXKEYS from '@src/ONYXKEYS';
import {PrivatePersonalDetails, Session} from '@src/types/onyx';
diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js
index 36cf9b1deadc..d170def12276 100644
--- a/src/components/CategoryPicker/index.js
+++ b/src/components/CategoryPicker/index.js
@@ -4,8 +4,8 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import OptionsSelector from '@components/OptionsSelector';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as OptionsListUtils from '@libs/OptionsListUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {defaultProps, propTypes} from './categoryPickerPropTypes';
diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx
index 5dd3164eadcc..23bc068e8fe0 100644
--- a/src/components/Checkbox.tsx
+++ b/src/components/Checkbox.tsx
@@ -1,8 +1,8 @@
import React, {ForwardedRef, forwardRef, KeyboardEvent as ReactKeyboardEvent} from 'react';
import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import Icon from './Icon';
diff --git a/src/components/CheckboxWithLabel.js b/src/components/CheckboxWithLabel.js
index 92cd7ea38eea..24f61c305dda 100644
--- a/src/components/CheckboxWithLabel.js
+++ b/src/components/CheckboxWithLabel.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, {useState} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import Checkbox from './Checkbox';
import FormHelpMessage from './FormHelpMessage';
diff --git a/src/components/CollapsibleSection/index.tsx b/src/components/CollapsibleSection/index.tsx
index 570d00559af8..bc7bf6e89dba 100644
--- a/src/components/CollapsibleSection/index.tsx
+++ b/src/components/CollapsibleSection/index.tsx
@@ -4,7 +4,7 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import Collapsible from './Collapsible';
@@ -32,7 +32,7 @@ function CollapsibleSection({title, children}: CollapsibleSectionProps) {
false,
isReportActionCompose: false,
isComposerFullSize: false,
+ shouldContainScroll: false,
};
/**
@@ -164,6 +169,7 @@ function Composer({
selection: selectionProp,
isReportActionCompose,
isComposerFullSize,
+ shouldContainScroll,
...props
}) {
const theme = useTheme();
@@ -180,6 +186,7 @@ function Composer({
const [caretContent, setCaretContent] = useState('');
const [valueBeforeCaret, setValueBeforeCaret] = useState('');
const [textInputWidth, setTextInputWidth] = useState('');
+ const isScrollBarVisible = useIsScrollBarVisible(textInput, value);
useEffect(() => {
if (!shouldClear) {
@@ -418,18 +425,26 @@ function Composer({
);
- const inputStyleMemo = useMemo(
- () => [
+ const scrollStyleMemo = useMemo(() => {
+ if (shouldContainScroll) {
+ return isScrollBarVisible ? [styles.overflowScroll, styles.overscrollBehaviorContain] : styles.overflowHidden;
+ }
+ return [
// We are hiding the scrollbar to prevent it from reducing the text input width,
// so we can get the correct scroll height while calculating the number of lines.
numberOfLines < maxLines ? styles.overflowHidden : {},
+ ];
+ }, [shouldContainScroll, isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]);
+ const inputStyleMemo = useMemo(
+ () => [
StyleSheet.flatten([style, {outline: 'none'}]),
StyleUtils.getComposeTextAreaPadding(numberOfLines, isComposerFullSize),
Browser.isMobileSafari() || Browser.isSafari() ? styles.rtlTextRenderForSafari : {},
+ scrollStyleMemo,
],
- [numberOfLines, maxLines, styles.overflowHidden, styles.rtlTextRenderForSafari, style, StyleUtils, isComposerFullSize],
+ [numberOfLines, scrollStyleMemo, styles.rtlTextRenderForSafari, style, StyleUtils, isComposerFullSize],
);
return (
diff --git a/src/components/ConfirmContent.js b/src/components/ConfirmContent.js
index ff8ee4f861a4..8574cc02014e 100644
--- a/src/components/ConfirmContent.js
+++ b/src/components/ConfirmContent.js
@@ -4,7 +4,7 @@ import {View} from 'react-native';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import Button from './Button';
import Header from './Header';
diff --git a/src/components/ConfirmationPage.tsx b/src/components/ConfirmationPage.tsx
index 12e8b40a0f25..21813edd693d 100644
--- a/src/components/ConfirmationPage.tsx
+++ b/src/components/ConfirmationPage.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Button from './Button';
import FixedFooter from './FixedFooter';
import Lottie from './Lottie';
diff --git a/src/components/ConfirmedRoute.js b/src/components/ConfirmedRoute.js
index 79b97b38194a..3abec6d0d1f4 100644
--- a/src/components/ConfirmedRoute.js
+++ b/src/components/ConfirmedRoute.js
@@ -5,9 +5,9 @@ import React, {useCallback, useEffect} from 'react';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useNetwork from '@hooks/useNetwork';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TransactionUtils from '@libs/TransactionUtils';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as MapboxToken from '@userActions/MapboxToken';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/ConnectBankAccountButton.js b/src/components/ConnectBankAccountButton.js
index 6afd3d57d4e6..f036918d9429 100644
--- a/src/components/ConnectBankAccountButton.js
+++ b/src/components/ConnectBankAccountButton.js
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as ReimbursementAccount from '@userActions/ReimbursementAccount';
import Button from './Button';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/ContextMenuItem.js b/src/components/ContextMenuItem.js
index 2cabd71b11cb..307cfcde9b10 100644
--- a/src/components/ContextMenuItem.js
+++ b/src/components/ContextMenuItem.js
@@ -1,10 +1,10 @@
import PropTypes from 'prop-types';
import React, {forwardRef, useImperativeHandle} from 'react';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import useThrottledButtonState from '@hooks/useThrottledButtonState';
import useWindowDimensions from '@hooks/useWindowDimensions';
import getButtonState from '@libs/getButtonState';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import BaseMiniContextMenuItem from './BaseMiniContextMenuItem';
import Icon from './Icon';
import MenuItem from './MenuItem';
diff --git a/src/components/CopyTextToClipboard.js b/src/components/CopyTextToClipboard.js
deleted file mode 100644
index 678537c6a3d7..000000000000
--- a/src/components/CopyTextToClipboard.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import PropTypes from 'prop-types';
-import React, {useCallback} from 'react';
-import Clipboard from '@libs/Clipboard';
-import * as Expensicons from './Icon/Expensicons';
-import PressableWithDelayToggle from './Pressable/PressableWithDelayToggle';
-import withLocalize, {withLocalizePropTypes} from './withLocalize';
-
-const propTypes = {
- /** The text to display and copy to the clipboard */
- text: PropTypes.string.isRequired,
-
- /** Styles to apply to the text */
- // eslint-disable-next-line react/forbid-prop-types
- textStyles: PropTypes.arrayOf(PropTypes.object),
- urlToCopy: PropTypes.string,
- accessibilityRole: PropTypes.string,
- ...withLocalizePropTypes,
-};
-
-const defaultProps = {
- textStyles: [],
- urlToCopy: null,
- accessibilityRole: undefined,
-};
-
-function CopyTextToClipboard(props) {
- const copyToClipboard = useCallback(() => {
- Clipboard.setString(props.urlToCopy || props.text);
- }, [props.text, props.urlToCopy]);
-
- return (
-
- );
-}
-
-CopyTextToClipboard.propTypes = propTypes;
-CopyTextToClipboard.defaultProps = defaultProps;
-CopyTextToClipboard.displayName = 'CopyTextToClipboard';
-
-export default withLocalize(CopyTextToClipboard);
diff --git a/src/components/CopyTextToClipboard.tsx b/src/components/CopyTextToClipboard.tsx
new file mode 100644
index 000000000000..6f3b42e88fee
--- /dev/null
+++ b/src/components/CopyTextToClipboard.tsx
@@ -0,0 +1,45 @@
+import React, {useCallback} from 'react';
+import {AccessibilityRole, StyleProp, TextStyle} from 'react-native';
+import useLocalize from '@hooks/useLocalize';
+import Clipboard from '@libs/Clipboard';
+import * as Expensicons from './Icon/Expensicons';
+import PressableWithDelayToggle from './Pressable/PressableWithDelayToggle';
+
+type CopyTextToClipboardProps = {
+ /** The text to display and copy to the clipboard */
+ text: string;
+
+ /** Styles to apply to the text */
+ textStyles?: StyleProp;
+
+ urlToCopy?: string;
+
+ accessibilityRole?: AccessibilityRole;
+};
+
+function CopyTextToClipboard({text, textStyles, urlToCopy, accessibilityRole}: CopyTextToClipboardProps) {
+ const {translate} = useLocalize();
+
+ const copyToClipboard = useCallback(() => {
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing doesn't achieve the same result in this case
+ Clipboard.setString(urlToCopy || text);
+ }, [text, urlToCopy]);
+
+ return (
+
+ );
+}
+
+CopyTextToClipboard.displayName = 'CopyTextToClipboard';
+
+export default CopyTextToClipboard;
diff --git a/src/components/CountrySelector.js b/src/components/CountrySelector.js
index b138bc949937..68a6486bce48 100644
--- a/src/components/CountrySelector.js
+++ b/src/components/CountrySelector.js
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React, {useEffect} from 'react';
import {View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import ROUTES from '@src/ROUTES';
import FormHelpMessage from './FormHelpMessage';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
diff --git a/src/components/CurrencySymbolButton.js b/src/components/CurrencySymbolButton.js
index 4d43ec3d93e0..d03834fc1fd6 100644
--- a/src/components/CurrencySymbolButton.js
+++ b/src/components/CurrencySymbolButton.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import Text from './Text';
@@ -23,7 +23,7 @@ function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol}) {
{currencySymbol}
diff --git a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx
index 6f6daddc51b8..02c308705994 100644
--- a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx
+++ b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx
@@ -3,9 +3,9 @@ import {View} from 'react-native';
import {Circle, Rect} from 'react-native-svg';
import {ValueOf} from 'type-fest';
import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
diff --git a/src/components/CurrentWalletBalance.tsx b/src/components/CurrentWalletBalance.tsx
index 9a5b2cd0227b..28a83fb1ae50 100644
--- a/src/components/CurrentWalletBalance.tsx
+++ b/src/components/CurrentWalletBalance.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {StyleProp, TextStyle} from 'react-native';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CurrencyUtils from '@libs/CurrencyUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import UserWallet from '@src/types/onyx/UserWallet';
import Text from './Text';
diff --git a/src/components/CustomStatusBar/index.tsx b/src/components/CustomStatusBar/index.tsx
index 3b5022c60898..2c1af898786d 100644
--- a/src/components/CustomStatusBar/index.tsx
+++ b/src/components/CustomStatusBar/index.tsx
@@ -1,30 +1,19 @@
import {EventListenerCallback, NavigationContainerEventMap} from '@react-navigation/native';
-import PropTypes from 'prop-types';
import React, {useCallback, useContext, useEffect} from 'react';
+import useTheme from '@hooks/useTheme';
import {navigationRef} from '@libs/Navigation/Navigation';
import StatusBar from '@libs/StatusBar';
-import useTheme from '@styles/themes/useTheme';
import CustomStatusBarContext from './CustomStatusBarContext';
import updateStatusBarAppearance from './updateStatusBarAppearance';
type CustomStatusBarProps = {
- isNested: boolean;
-};
-
-const propTypes = {
/** Whether the CustomStatusBar is nested within another CustomStatusBar.
* A nested CustomStatusBar will disable the "root" CustomStatusBar. */
- isNested: PropTypes.bool,
-};
-
-type CustomStatusBarType = {
- (props: CustomStatusBarProps): React.ReactNode;
- displayName: string;
- propTypes: typeof propTypes;
+ isNested: boolean;
};
// eslint-disable-next-line react/function-component-definition
-const CustomStatusBar: CustomStatusBarType = ({isNested = false}) => {
+function CustomStatusBar({isNested = false}: CustomStatusBarProps) {
const {isRootStatusBarDisabled, disableRootStatusBar} = useContext(CustomStatusBarContext);
const theme = useTheme();
@@ -83,9 +72,8 @@ const CustomStatusBar: CustomStatusBarType = ({isNested = false}) => {
}
return ;
-};
+}
CustomStatusBar.displayName = 'CustomStatusBar';
-CustomStatusBar.propTypes = propTypes;
export default CustomStatusBar;
diff --git a/src/components/CustomStatusBar/updateStatusBarAppearance/types.ts b/src/components/CustomStatusBar/updateStatusBarAppearance/types.ts
index 3d16b5944a31..823f0059eccf 100644
--- a/src/components/CustomStatusBar/updateStatusBarAppearance/types.ts
+++ b/src/components/CustomStatusBar/updateStatusBarAppearance/types.ts
@@ -1,4 +1,4 @@
-import {StatusBarStyle} from '@styles/styles';
+import {StatusBarStyle} from '@styles/index';
type UpdateStatusBarAppearanceProps = {
backgroundColor?: string;
diff --git a/src/components/DatePicker/CalendarPicker/ArrowIcon.js b/src/components/DatePicker/CalendarPicker/ArrowIcon.js
index a03e18085706..793aca9e7635 100644
--- a/src/components/DatePicker/CalendarPicker/ArrowIcon.js
+++ b/src/components/DatePicker/CalendarPicker/ArrowIcon.js
@@ -3,8 +3,8 @@ import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/components/DatePicker/CalendarPicker/YearPickerModal.js b/src/components/DatePicker/CalendarPicker/YearPickerModal.js
index f51d869efbac..e8883648051c 100644
--- a/src/components/DatePicker/CalendarPicker/YearPickerModal.js
+++ b/src/components/DatePicker/CalendarPicker/YearPickerModal.js
@@ -7,7 +7,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import {radioListItemPropTypes} from '@components/SelectionList/selectionListPropTypes';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/components/DatePicker/index.js b/src/components/DatePicker/index.js
index 10a53dc25bbb..8af550c9dc66 100644
--- a/src/components/DatePicker/index.js
+++ b/src/components/DatePicker/index.js
@@ -8,7 +8,7 @@ import * as Expensicons from '@components/Icon/Expensicons';
import TextInput from '@components/TextInput';
import {propTypes as baseTextInputPropTypes, defaultProps as defaultBaseTextInputPropTypes} from '@components/TextInput/BaseTextInput/baseTextInputPropTypes';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import CalendarPicker from './CalendarPicker';
@@ -76,7 +76,7 @@ function DatePicker({containerStyles, defaultValue, disabled, errorText, inputID
icon={Expensicons.Calendar}
label={label}
accessibilityLabel={label}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
value={value || selectedDate || ''}
placeholder={placeholder || translate('common.dateFormat')}
errorText={errorText}
diff --git a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.js b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.js
index 3c7366949ac1..622767b8a5f8 100644
--- a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.js
+++ b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.js
@@ -8,10 +8,10 @@ import * as Illustrations from '@components/Icon/Illustrations';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/components/DeeplinkWrapper/index.website.js b/src/components/DeeplinkWrapper/index.website.js
index 166818e4ae27..d81c99657dd8 100644
--- a/src/components/DeeplinkWrapper/index.website.js
+++ b/src/components/DeeplinkWrapper/index.website.js
@@ -16,6 +16,8 @@ const propTypes = {
children: PropTypes.node.isRequired,
/** User authentication status */
isAuthenticated: PropTypes.bool.isRequired,
+ /** The auto authentication status */
+ autoAuthState: PropTypes.string,
};
function isMacOSWeb() {
@@ -36,7 +38,7 @@ function promptToOpenInDesktopApp() {
App.beginDeepLinkRedirect(!isMagicLink);
}
}
-function DeeplinkWrapper({children, isAuthenticated}) {
+function DeeplinkWrapper({children, isAuthenticated, autoAuthState}) {
const [currentScreen, setCurrentScreen] = useState();
const [hasShownPrompt, setHasShownPrompt] = useState(false);
const removeListener = useRef();
@@ -69,7 +71,7 @@ function DeeplinkWrapper({children, isAuthenticated}) {
return routeRegex.test(window.location.pathname);
});
// Making a few checks to exit early before checking authentication status
- if (!isMacOSWeb() || isUnsupportedDeeplinkRoute || CONFIG.ENVIRONMENT === CONST.ENVIRONMENT.DEV || hasShownPrompt) {
+ if (!isMacOSWeb() || isUnsupportedDeeplinkRoute || hasShownPrompt || CONFIG.ENVIRONMENT === CONST.ENVIRONMENT.DEV || autoAuthState === CONST.AUTO_AUTH_STATE.NOT_STARTED) {
return;
}
// We want to show the prompt immediately if the user is already authenticated.
@@ -92,7 +94,7 @@ function DeeplinkWrapper({children, isAuthenticated}) {
promptToOpenInDesktopApp();
setHasShownPrompt(true);
}
- }, [currentScreen, hasShownPrompt, isAuthenticated]);
+ }, [currentScreen, hasShownPrompt, isAuthenticated, autoAuthState]);
return children;
}
diff --git a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
index 82f9c5799b78..440457d22965 100644
--- a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
+++ b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx
@@ -2,8 +2,8 @@ import React, {RefObject, useCallback} from 'react';
import {Text as RNText, StyleProp, TextStyle} from 'react-native';
import Text from '@components/Text';
import UserDetailsTooltip from '@components/UserDetailsTooltip';
+import useThemeStyles from '@hooks/useThemeStyles';
import {AvatarSource} from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
type DisplayNamesTooltipItemProps = {
index?: number;
diff --git a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx
index 8c8720c7c99f..43061ada9a94 100644
--- a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx
+++ b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx
@@ -2,7 +2,7 @@ import React, {Fragment, useCallback, useRef} from 'react';
import {Text as RNText, View} from 'react-native';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import DisplayNamesTooltipItem from './DisplayNamesTooltipItem';
import DisplayNamesProps from './types';
diff --git a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx
index 1854ebe2353d..761b0b66ee2c 100644
--- a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx
+++ b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {StyleProp, TextStyle} from 'react-native';
import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
type DisplayNamesWithoutTooltipProps = {
/** The full title of the DisplayNames component (not split up) */
diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js
index cbf25fd2753b..7d1d3c99f48d 100644
--- a/src/components/DistanceEReceipt.js
+++ b/src/components/DistanceEReceipt.js
@@ -5,13 +5,13 @@ import _ from 'underscore';
import EReceiptBackground from '@assets/images/eReceipt_background.svg';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import PendingMapView from './MapView/PendingMapView';
diff --git a/src/components/DistanceMapView/index.android.js b/src/components/DistanceMapView/index.android.js
index 532d42ac0be5..fa40bd50673e 100644
--- a/src/components/DistanceMapView/index.android.js
+++ b/src/components/DistanceMapView/index.android.js
@@ -6,8 +6,8 @@ import * as Expensicons from '@components/Icon/Expensicons';
import MapView from '@components/MapView';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as distanceMapViewPropTypes from './distanceMapViewPropTypes';
function DistanceMapView(props) {
diff --git a/src/components/DistanceRequest/DistanceRequestFooter.js b/src/components/DistanceRequest/DistanceRequestFooter.js
index d374f90a1b6c..d2813c152a64 100644
--- a/src/components/DistanceRequest/DistanceRequestFooter.js
+++ b/src/components/DistanceRequest/DistanceRequestFooter.js
@@ -10,9 +10,9 @@ import DistanceMapView from '@components/DistanceMapView';
import * as Expensicons from '@components/Icon/Expensicons';
import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TransactionUtils from '@libs/TransactionUtils';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/DistanceRequest/DistanceRequestRenderItem.js b/src/components/DistanceRequest/DistanceRequestRenderItem.js
index 1735e244a347..2aa2ac58f379 100644
--- a/src/components/DistanceRequest/DistanceRequestRenderItem.js
+++ b/src/components/DistanceRequest/DistanceRequestRenderItem.js
@@ -5,7 +5,7 @@ import _ from 'underscore';
import * as Expensicons from '@components/Icon/Expensicons';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import useLocalize from '@hooks/useLocalize';
-import useTheme from '@styles/themes/useTheme';
+import useTheme from '@hooks/useTheme';
const propTypes = {
/** The waypoints for the distance request */
diff --git a/src/components/DistanceRequest/index.js b/src/components/DistanceRequest/index.js
index be34a42ead5e..b2fd16cb7d97 100644
--- a/src/components/DistanceRequest/index.js
+++ b/src/components/DistanceRequest/index.js
@@ -14,12 +14,12 @@ import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as TransactionUtils from '@libs/TransactionUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as MapboxToken from '@userActions/MapboxToken';
import * as Transaction from '@userActions/Transaction';
diff --git a/src/components/DotIndicatorMessage.tsx b/src/components/DotIndicatorMessage.tsx
index 6a7d78768ed7..65afe8c7e4eb 100644
--- a/src/components/DotIndicatorMessage.tsx
+++ b/src/components/DotIndicatorMessage.tsx
@@ -1,11 +1,11 @@
/* eslint-disable react/no-array-index-key */
import React from 'react';
import {StyleProp, TextStyle, View, ViewStyle} from 'react-native';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import fileDownload from '@libs/fileDownload';
import * as Localize from '@libs/Localize';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/DragAndDrop/NoDropZone/index.tsx b/src/components/DragAndDrop/NoDropZone/index.tsx
index 9f2c700b8918..4760a16fd20b 100644
--- a/src/components/DragAndDrop/NoDropZone/index.tsx
+++ b/src/components/DragAndDrop/NoDropZone/index.tsx
@@ -1,7 +1,7 @@
import React, {useRef} from 'react';
import {View} from 'react-native';
import useDragAndDrop from '@hooks/useDragAndDrop';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import type NoDropZoneProps from './types';
function NoDropZone({children}: NoDropZoneProps) {
diff --git a/src/components/DragAndDrop/Provider/index.tsx b/src/components/DragAndDrop/Provider/index.tsx
index 761c512497ac..a5da9cc45a36 100644
--- a/src/components/DragAndDrop/Provider/index.tsx
+++ b/src/components/DragAndDrop/Provider/index.tsx
@@ -3,7 +3,7 @@ import Str from 'expensify-common/lib/str';
import React, {useCallback, useEffect, useMemo, useRef} from 'react';
import {View} from 'react-native';
import useDragAndDrop from '@hooks/useDragAndDrop';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {DragAndDropContextParams, DragAndDropProviderProps, SetOnDropHandlerCallback} from './types';
const DragAndDropContext = React.createContext({});
diff --git a/src/components/DraggableList/index.native.tsx b/src/components/DraggableList/index.native.tsx
index e7ff058234b7..f532b21720da 100644
--- a/src/components/DraggableList/index.native.tsx
+++ b/src/components/DraggableList/index.native.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import DraggableFlatList from 'react-native-draggable-flatlist';
import {FlatList} from 'react-native-gesture-handler';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {DraggableListProps} from './types';
function DraggableList({renderClone, shouldUsePortal, ...viewProps}: DraggableListProps, ref: React.ForwardedRef>) {
diff --git a/src/components/DraggableList/index.tsx b/src/components/DraggableList/index.tsx
index 28128002c589..b92691075424 100644
--- a/src/components/DraggableList/index.tsx
+++ b/src/components/DraggableList/index.tsx
@@ -1,7 +1,7 @@
import React, {useCallback} from 'react';
import {DragDropContext, Draggable, Droppable, type OnDragEndResponder} from 'react-beautiful-dnd';
import {ScrollView} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {DraggableListProps} from './types';
import useDraggableInPortal from './useDraggableInPortal';
diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js
index f5e5b7f2f6b3..12cea0df04ac 100644
--- a/src/components/EReceipt.js
+++ b/src/components/EReceipt.js
@@ -3,11 +3,11 @@ import React from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/EReceiptThumbnail.js b/src/components/EReceiptThumbnail.js
index 1f719862412b..7c782a0aa327 100644
--- a/src/components/EReceiptThumbnail.js
+++ b/src/components/EReceiptThumbnail.js
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
import React, {useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportUtils from '@libs/ReportUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/EmojiPicker/CategoryShortcutBar.js b/src/components/EmojiPicker/CategoryShortcutBar.js
index c0c9fb8ea161..facafea13a70 100644
--- a/src/components/EmojiPicker/CategoryShortcutBar.js
+++ b/src/components/EmojiPicker/CategoryShortcutBar.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CategoryShortcutButton from './CategoryShortcutButton';
const propTypes = {
diff --git a/src/components/EmojiPicker/CategoryShortcutButton.js b/src/components/EmojiPicker/CategoryShortcutButton.js
index 8738f210276e..a7dc0d7bf564 100644
--- a/src/components/EmojiPicker/CategoryShortcutButton.js
+++ b/src/components/EmojiPicker/CategoryShortcutButton.js
@@ -4,10 +4,10 @@ import Icon from '@components/Icon';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import getButtonState from '@libs/getButtonState';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
@@ -41,7 +41,7 @@ function CategoryShortcutButton(props) {
onHoverOut={() => setIsHighlighted(false)}
style={({pressed}) => [StyleUtils.getButtonBackgroundColorStyle(getButtonState(false, pressed)), styles.categoryShortcutButton, isHighlighted && styles.emojiItemHighlighted]}
accessibilityLabel={`emojiPicker.headers.${props.code}`}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{({hovered, pressed}) => (
diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js
index 95db6eb41167..36594dabcd30 100755
--- a/src/components/EmojiPicker/EmojiPickerMenu/index.js
+++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js
@@ -11,6 +11,8 @@ import EmojiSkinToneList from '@components/EmojiPicker/EmojiSkinToneList';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
@@ -18,8 +20,6 @@ import compose from '@libs/compose';
import * as EmojiUtils from '@libs/EmojiUtils';
import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition';
import * as ReportUtils from '@libs/ReportUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -485,7 +485,7 @@ function EmojiPickerMenu(props) {
0}
/>
diff --git a/src/components/EmojiPicker/EmojiPickerMenuItem/index.js b/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
index ae2cdf46dfc0..52d4a0db8812 100644
--- a/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
+++ b/src/components/EmojiPicker/EmojiPickerMenuItem/index.js
@@ -103,7 +103,7 @@ class EmojiPickerMenuItem extends PureComponent {
this.props.themeStyles.emojiItem,
]}
accessibilityLabel={this.props.emoji}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{this.props.emoji}
diff --git a/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js b/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
index 7934cc0f03d4..1726ff5b6543 100644
--- a/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
+++ b/src/components/EmojiPicker/EmojiPickerMenuItem/index.native.js
@@ -80,7 +80,7 @@ class EmojiPickerMenuItem extends PureComponent {
this.props.themeStyles.emojiItem,
]}
accessibilityLabel={this.props.emoji}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{this.props.emoji}
diff --git a/src/components/EmojiPicker/EmojiSkinToneList.js b/src/components/EmojiPicker/EmojiSkinToneList.js
index 25fc9ad0836a..2b574b0b533f 100644
--- a/src/components/EmojiPicker/EmojiSkinToneList.js
+++ b/src/components/EmojiPicker/EmojiSkinToneList.js
@@ -6,7 +6,7 @@ import * as Emojis from '@assets/emojis';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import EmojiPickerMenuItem from './EmojiPickerMenuItem';
import getSkinToneEmojiFromIndex from './getSkinToneEmojiFromIndex';
@@ -49,7 +49,7 @@ function EmojiSkinToneList(props) {
onPress={toggleIsSkinToneListVisible}
style={[styles.flexRow, styles.alignSelfCenter, styles.justifyContentStart, styles.alignItemsCenter]}
accessibilityLabel={props.translate('emojiPicker.skinTonePickerLabel')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{currentSkinTone.code}
diff --git a/src/components/EmojiSuggestions.tsx b/src/components/EmojiSuggestions.tsx
index 01f840677e5e..2fcf8e827b4e 100644
--- a/src/components/EmojiSuggestions.tsx
+++ b/src/components/EmojiSuggestions.tsx
@@ -1,10 +1,10 @@
import React, {ReactElement, useCallback} from 'react';
import {View} from 'react-native';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {SimpleEmoji} from '@libs/EmojiTrie';
import * as EmojiUtils from '@libs/EmojiUtils';
import getStyledTextArray from '@libs/GetStyledTextArray';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import AutoCompleteSuggestions from './AutoCompleteSuggestions';
import Text from './Text';
diff --git a/src/components/EnvironmentBadge.tsx b/src/components/EnvironmentBadge.tsx
index a3f321072988..6babbf119445 100644
--- a/src/components/EnvironmentBadge.tsx
+++ b/src/components/EnvironmentBadge.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import useEnvironment from '@hooks/useEnvironment';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Environment from '@libs/Environment/Environment';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import pkg from '../../package.json';
import Badge from './Badge';
diff --git a/src/components/ExceededCommentLength.js b/src/components/ExceededCommentLength.js
index 6353bdf40283..3fd6688944f7 100644
--- a/src/components/ExceededCommentLength.js
+++ b/src/components/ExceededCommentLength.js
@@ -1,52 +1,23 @@
-import {debounce} from 'lodash';
import PropTypes from 'prop-types';
-import React, {useEffect, useMemo, useState} from 'react';
-import {withOnyx} from 'react-native-onyx';
+import React from 'react';
import useLocalize from '@hooks/useLocalize';
-import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
import Text from './Text';
const propTypes = {
- /** Report ID to get the comment from (used in withOnyx) */
- // eslint-disable-next-line react/no-unused-prop-types
- reportID: PropTypes.string.isRequired,
-
- /** Text Comment */
- comment: PropTypes.string,
-
- /** Update UI on parent when comment length is exceeded */
- onExceededMaxCommentLength: PropTypes.func.isRequired,
+ shouldShowError: PropTypes.bool.isRequired,
};
-const defaultProps = {
- comment: '',
-};
+const defaultProps = {};
function ExceededCommentLength(props) {
const styles = useThemeStyles();
const {numberFormat, translate} = useLocalize();
- const [commentLength, setCommentLength] = useState(0);
- const updateCommentLength = useMemo(
- () =>
- debounce((comment, onExceededMaxCommentLength) => {
- const newCommentLength = ReportUtils.getCommentLength(comment);
- setCommentLength(newCommentLength);
- onExceededMaxCommentLength(newCommentLength > CONST.MAX_COMMENT_LENGTH);
- }, CONST.TIMING.COMMENT_LENGTH_DEBOUNCE_TIME),
- [],
- );
-
- useEffect(() => {
- updateCommentLength(props.comment, props.onExceededMaxCommentLength);
- }, [props.comment, props.onExceededMaxCommentLength, updateCommentLength]);
- if (commentLength <= CONST.MAX_COMMENT_LENGTH) {
+ if (!props.shouldShowError) {
return null;
}
-
return (
`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`,
- initialValue: '',
- },
-})(ExceededCommentLength);
+export default ExceededCommentLength;
diff --git a/src/components/ExpensifyWordmark.tsx b/src/components/ExpensifyWordmark.tsx
index 49559d1cc6d5..b1ef7c093e29 100644
--- a/src/components/ExpensifyWordmark.tsx
+++ b/src/components/ExpensifyWordmark.tsx
@@ -5,9 +5,9 @@ import DevLogo from '@assets/images/expensify-logo--dev.svg';
import StagingLogo from '@assets/images/expensify-logo--staging.svg';
import ProductionLogo from '@assets/images/expensify-wordmark.svg';
import useEnvironment from '@hooks/useEnvironment';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import withWindowDimensions from './withWindowDimensions';
diff --git a/src/components/FeatureList.js b/src/components/FeatureList.js
index 7b0c70372579..bf0852d179f1 100644
--- a/src/components/FeatureList.js
+++ b/src/components/FeatureList.js
@@ -3,7 +3,7 @@ import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import MenuItem from './MenuItem';
import menuItemPropTypes from './menuItemPropTypes';
import Text from './Text';
diff --git a/src/components/FixedFooter.tsx b/src/components/FixedFooter.tsx
index 4b32e1b8ce81..7fd6811c1df6 100644
--- a/src/components/FixedFooter.tsx
+++ b/src/components/FixedFooter.tsx
@@ -1,6 +1,6 @@
import React, {ReactNode} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
type FixedFooterProps = {
/** Children to wrap in FixedFooter. */
diff --git a/src/components/FocusModeNotification.js b/src/components/FocusModeNotification.js
index ea6db244091a..e846c1f188e2 100644
--- a/src/components/FocusModeNotification.js
+++ b/src/components/FocusModeNotification.js
@@ -1,7 +1,7 @@
import React, {useEffect} from 'react';
import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Link from '@userActions/Link';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
@@ -10,9 +10,9 @@ import Text from './Text';
import TextLinkWithRef from './TextLink';
function FocusModeNotification() {
+ const styles = useThemeStyles();
const {environmentURL} = useEnvironment();
const {translate} = useLocalize();
- const styles = useThemeStyles();
useEffect(() => {
User.updateChatPriorityMode(CONST.PRIORITY_MODE.GSD, true);
}, []);
diff --git a/src/components/Form.js b/src/components/Form.js
index ad5fcf611e9b..7b6f587e7bd1 100644
--- a/src/components/Form.js
+++ b/src/components/Form.js
@@ -1,16 +1,16 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {Keyboard, ScrollView, StyleSheet} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import FormUtils from '@libs/FormUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import Visibility from '@libs/Visibility';
import stylePropTypes from '@styles/stylePropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
import FormAlertWithSubmitButton from './FormAlertWithSubmitButton';
@@ -26,7 +26,7 @@ const propTypes = {
formID: PropTypes.string.isRequired,
/** Text to be displayed in the submit button */
- submitButtonText: PropTypes.string.isRequired,
+ submitButtonText: PropTypes.string,
/** Controls the submit button's visibility */
isSubmitButtonVisible: PropTypes.bool,
@@ -88,6 +88,9 @@ const propTypes = {
/** Information about the network */
network: networkPropTypes.isRequired,
+ /** Style for the error message for submit button */
+ errorMessageStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
+
...withLocalizePropTypes,
};
@@ -104,11 +107,13 @@ const defaultProps = {
shouldValidateOnBlur: true,
footerContent: null,
style: [],
+ errorMessageStyle: [],
submitButtonStyles: [],
validate: () => ({}),
+ submitButtonText: '',
};
-function Form(props) {
+const Form = forwardRef((props, forwardedRef) => {
const styles = useThemeStyles();
const [errors, setErrors] = useState({});
const [inputValues, setInputValues] = useState(() => ({...props.draftValues}));
@@ -245,6 +250,30 @@ function Form(props) {
onSubmit(trimmedStringValues);
}, [props.formState.isLoading, props.network.isOffline, props.enabledWhenOffline, inputValues, onValidate, onSubmit]);
+ /**
+ * Resets the form
+ */
+ const resetForm = useCallback(
+ (optionalValue) => {
+ _.each(inputValues, (inputRef, inputID) => {
+ setInputValues((prevState) => {
+ const copyPrevState = _.clone(prevState);
+
+ touchedInputs.current[inputID] = false;
+ copyPrevState[inputID] = optionalValue[inputID] || '';
+
+ return copyPrevState;
+ });
+ });
+ setErrors({});
+ },
+ [inputValues],
+ );
+
+ useImperativeHandle(forwardedRef, () => ({
+ resetForm,
+ }));
+
/**
* Loops over Form's children and automatically supplies Form props to them
*
@@ -464,7 +493,9 @@ function Form(props) {
containerStyles={[styles.mh0, styles.mt5, styles.flex1, ...props.submitButtonStyles]}
enabledWhenOffline={props.enabledWhenOffline}
isSubmitActionDangerous={props.isSubmitActionDangerous}
+ useSmallerSubmitButtonSize={props.useSmallerSubmitButtonSize}
disablePressOnEnter
+ errorMessageStyle={props.errorMessageStyle}
/>
)}
@@ -474,6 +505,8 @@ function Form(props) {
props.style,
props.isSubmitButtonVisible,
props.submitButtonText,
+ props.useSmallerSubmitButtonSize,
+ props.errorMessageStyle,
props.formState.errorFields,
props.formState.isLoading,
props.footerContent,
@@ -539,7 +572,7 @@ function Form(props) {
}
);
-}
+});
Form.displayName = 'Form';
Form.propTypes = propTypes;
diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js
index 63953d8303db..0d6dcb001091 100644
--- a/src/components/Form/FormProvider.js
+++ b/src/components/Form/FormProvider.js
@@ -1,6 +1,6 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
-import React, {createRef, useCallback, useMemo, useRef, useState} from 'react';
+import React, {createRef, forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import networkPropTypes from '@components/networkPropTypes';
@@ -109,250 +109,278 @@ function getInitialValueByType(valueType) {
}
}
-function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnChange, children, formState, network, enabledWhenOffline, draftValues, onSubmit, ...rest}) {
- const inputRefs = useRef({});
- const touchedInputs = useRef({});
- const [inputValues, setInputValues] = useState(() => ({...draftValues}));
- const [errors, setErrors] = useState({});
- const hasServerError = useMemo(() => Boolean(formState) && !_.isEmpty(formState.errors), [formState]);
+const FormProvider = forwardRef(
+ ({validate, formID, shouldValidateOnBlur, shouldValidateOnChange, children, formState, network, enabledWhenOffline, draftValues, onSubmit, ...rest}, forwardedRef) => {
+ const inputRefs = useRef({});
+ const touchedInputs = useRef({});
+ const [inputValues, setInputValues] = useState(() => ({...draftValues}));
+ const [errors, setErrors] = useState({});
+ const hasServerError = useMemo(() => Boolean(formState) && !_.isEmpty(formState.errors), [formState]);
- const onValidate = useCallback(
- (values, shouldClearServerError = true) => {
- const trimmedStringValues = ValidationUtils.prepareValues(values);
+ const onValidate = useCallback(
+ (values, shouldClearServerError = true) => {
+ const trimmedStringValues = ValidationUtils.prepareValues(values);
- if (shouldClearServerError) {
- FormActions.setErrors(formID, null);
- }
- FormActions.setErrorFields(formID, null);
+ if (shouldClearServerError) {
+ FormActions.setErrors(formID, null);
+ }
+ FormActions.setErrorFields(formID, null);
- const validateErrors = validate(values) || {};
+ const validateErrors = validate(values) || {};
- // Validate the input for html tags. It should supercede any other error
- _.each(trimmedStringValues, (inputValue, inputID) => {
- // If the input value is empty OR is non-string, we don't need to validate it for HTML tags
- if (!inputValue || !_.isString(inputValue)) {
- return;
- }
- const foundHtmlTagIndex = inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
- const leadingSpaceIndex = inputValue.search(CONST.VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX);
+ // Validate the input for html tags. It should supercede any other error
+ _.each(trimmedStringValues, (inputValue, inputID) => {
+ // If the input value is empty OR is non-string, we don't need to validate it for HTML tags
+ if (!inputValue || !_.isString(inputValue)) {
+ return;
+ }
+ const foundHtmlTagIndex = inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
+ const leadingSpaceIndex = inputValue.search(CONST.VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX);
- // Return early if there are no HTML characters
- if (leadingSpaceIndex === -1 && foundHtmlTagIndex === -1) {
- return;
- }
+ // Return early if there are no HTML characters
+ if (leadingSpaceIndex === -1 && foundHtmlTagIndex === -1) {
+ return;
+ }
- const matchedHtmlTags = inputValue.match(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
- let isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(inputValue));
- // Check for any matches that the original regex (foundHtmlTagIndex) matched
- if (matchedHtmlTags) {
- // Check if any matched inputs does not match in WHITELISTED_TAGS list and return early if needed.
- for (let i = 0; i < matchedHtmlTags.length; i++) {
- const htmlTag = matchedHtmlTags[i];
- isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(htmlTag));
- if (!isMatch) {
- break;
+ const matchedHtmlTags = inputValue.match(CONST.VALIDATE_FOR_HTML_TAG_REGEX);
+ let isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(inputValue));
+ // Check for any matches that the original regex (foundHtmlTagIndex) matched
+ if (matchedHtmlTags) {
+ // Check if any matched inputs does not match in WHITELISTED_TAGS list and return early if needed.
+ for (let i = 0; i < matchedHtmlTags.length; i++) {
+ const htmlTag = matchedHtmlTags[i];
+ isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(htmlTag));
+ if (!isMatch) {
+ break;
+ }
}
}
+ // Add a validation error here because it is a string value that contains HTML characters
+ validateErrors[inputID] = 'common.error.invalidCharacter';
+ });
+
+ if (!_.isObject(validateErrors)) {
+ throw new Error('Validate callback must return an empty object or an object with shape {inputID: error}');
}
- // Add a validation error here because it is a string value that contains HTML characters
- validateErrors[inputID] = 'common.error.invalidCharacter';
- });
- if (!_.isObject(validateErrors)) {
- throw new Error('Validate callback must return an empty object or an object with shape {inputID: error}');
- }
+ const touchedInputErrors = _.pick(validateErrors, (inputValue, inputID) => Boolean(touchedInputs.current[inputID]));
- const touchedInputErrors = _.pick(validateErrors, (inputValue, inputID) => Boolean(touchedInputs.current[inputID]));
+ if (!_.isEqual(errors, touchedInputErrors)) {
+ setErrors(touchedInputErrors);
+ }
- if (!_.isEqual(errors, touchedInputErrors)) {
- setErrors(touchedInputErrors);
+ return touchedInputErrors;
+ },
+ [errors, formID, validate],
+ );
+
+ /**
+ * @param {String} inputID - The inputID of the input being touched
+ */
+ const setTouchedInput = useCallback(
+ (inputID) => {
+ touchedInputs.current[inputID] = true;
+ },
+ [touchedInputs],
+ );
+
+ const submit = useCallback(() => {
+ // Return early if the form is already submitting to avoid duplicate submission
+ if (formState.isLoading) {
+ return;
}
- return touchedInputErrors;
- },
- [errors, formID, validate],
- );
-
- /**
- * @param {String} inputID - The inputID of the input being touched
- */
- const setTouchedInput = useCallback(
- (inputID) => {
- touchedInputs.current[inputID] = true;
- },
- [touchedInputs],
- );
-
- const submit = useCallback(() => {
- // Return early if the form is already submitting to avoid duplicate submission
- if (formState.isLoading) {
- return;
- }
-
- // Prepare values before submitting
- const trimmedStringValues = ValidationUtils.prepareValues(inputValues);
-
- // Touches all form inputs so we can validate the entire form
- _.each(inputRefs.current, (inputRef, inputID) => (touchedInputs.current[inputID] = true));
-
- // Validate form and return early if any errors are found
- if (!_.isEmpty(onValidate(trimmedStringValues))) {
- return;
- }
-
- // Do not submit form if network is offline and the form is not enabled when offline
- if (network.isOffline && !enabledWhenOffline) {
- return;
- }
-
- onSubmit(trimmedStringValues);
- }, [enabledWhenOffline, formState.isLoading, inputValues, network.isOffline, onSubmit, onValidate]);
-
- const registerInput = useCallback(
- (inputID, propsToParse = {}) => {
- const newRef = inputRefs.current[inputID] || propsToParse.ref || createRef();
- if (inputRefs.current[inputID] !== newRef) {
- inputRefs.current[inputID] = newRef;
+ // Prepare values before submitting
+ const trimmedStringValues = ValidationUtils.prepareValues(inputValues);
+
+ // Touches all form inputs so we can validate the entire form
+ _.each(inputRefs.current, (inputRef, inputID) => (touchedInputs.current[inputID] = true));
+
+ // Validate form and return early if any errors are found
+ if (!_.isEmpty(onValidate(trimmedStringValues))) {
+ return;
}
- if (!_.isUndefined(propsToParse.value)) {
- inputValues[inputID] = propsToParse.value;
- } else if (propsToParse.shouldSaveDraft && !_.isUndefined(draftValues[inputID]) && _.isUndefined(inputValues[inputID])) {
- inputValues[inputID] = draftValues[inputID];
- } else if (propsToParse.shouldUseDefaultValue && _.isUndefined(inputValues[inputID])) {
- // We force the form to set the input value from the defaultValue props if there is a saved valid value
- inputValues[inputID] = propsToParse.defaultValue;
- } else if (_.isUndefined(inputValues[inputID])) {
- // We want to initialize the input value if it's undefined
- inputValues[inputID] = _.isUndefined(propsToParse.defaultValue) ? getInitialValueByType(propsToParse.valueType) : propsToParse.defaultValue;
+ // Do not submit form if network is offline and the form is not enabled when offline
+ if (network.isOffline && !enabledWhenOffline) {
+ return;
}
- const errorFields = lodashGet(formState, 'errorFields', {});
- const fieldErrorMessage =
- _.chain(errorFields[inputID])
- .keys()
- .sortBy()
- .reverse()
- .map((key) => errorFields[inputID][key])
- .first()
- .value() || '';
-
- return {
- ...propsToParse,
- ref:
- typeof propsToParse.ref === 'function'
- ? (node) => {
- propsToParse.ref(node);
- newRef.current = node;
- }
- : newRef,
- inputID,
- key: propsToParse.key || inputID,
- errorText: errors[inputID] || fieldErrorMessage,
- value: inputValues[inputID],
- // As the text input is controlled, we never set the defaultValue prop
- // as this is already happening by the value prop.
- defaultValue: undefined,
- onTouched: (event) => {
- if (!propsToParse.shouldSetTouchedOnBlurOnly) {
- setTimeout(() => {
- setTouchedInput(inputID);
- }, VALIDATE_DELAY);
- }
- if (_.isFunction(propsToParse.onTouched)) {
- propsToParse.onTouched(event);
- }
- },
- onPress: (event) => {
- if (!propsToParse.shouldSetTouchedOnBlurOnly) {
- setTimeout(() => {
- setTouchedInput(inputID);
- }, VALIDATE_DELAY);
- }
- if (_.isFunction(propsToParse.onPress)) {
- propsToParse.onPress(event);
- }
- },
- onPressOut: (event) => {
- // To prevent validating just pressed inputs, we need to set the touched input right after
- // onValidate and to do so, we need to delays setTouchedInput of the same amount of time
- // as the onValidate is delayed
- if (!propsToParse.shouldSetTouchedOnBlurOnly) {
- setTimeout(() => {
- setTouchedInput(inputID);
- }, VALIDATE_DELAY);
- }
- if (_.isFunction(propsToParse.onPressIn)) {
- propsToParse.onPressIn(event);
- }
- },
- onBlur: (event) => {
- // Only run validation when user proactively blurs the input.
- if (Visibility.isVisible() && Visibility.hasFocus()) {
- const relatedTargetId = lodashGet(event, 'nativeEvent.relatedTarget.id');
- // We delay the validation in order to prevent Checkbox loss of focus when
- // the user is focusing a TextInput and proceeds to toggle a CheckBox in
- // web and mobile web platforms.
-
- setTimeout(() => {
- if (relatedTargetId && _.includes([CONST.OVERLAY.BOTTOM_BUTTON_NATIVE_ID, CONST.OVERLAY.TOP_BUTTON_NATIVE_ID, CONST.BACK_BUTTON_NATIVE_ID], relatedTargetId)) {
- return;
- }
- setTouchedInput(inputID);
- if (shouldValidateOnBlur) {
- onValidate(inputValues, !hasServerError);
- }
- }, VALIDATE_DELAY);
- }
+ onSubmit(trimmedStringValues);
+ }, [enabledWhenOffline, formState.isLoading, inputValues, network.isOffline, onSubmit, onValidate]);
- if (_.isFunction(propsToParse.onBlur)) {
- propsToParse.onBlur(event);
- }
- },
- onInputChange: (value, key) => {
- const inputKey = key || inputID;
+ /**
+ * Resets the form
+ */
+ const resetForm = useCallback(
+ (optionalValue) => {
+ _.each(inputValues, (inputRef, inputID) => {
setInputValues((prevState) => {
- const newState = {
- ...prevState,
- [inputKey]: value,
- };
+ const copyPrevState = _.clone(prevState);
- if (shouldValidateOnChange) {
- onValidate(newState);
- }
- return newState;
+ touchedInputs.current[inputID] = false;
+ copyPrevState[inputID] = optionalValue[inputID] || '';
+
+ return copyPrevState;
});
+ });
+ setErrors({});
+ },
+ [inputValues],
+ );
+ useImperativeHandle(forwardedRef, () => ({
+ resetForm,
+ }));
+
+ const registerInput = useCallback(
+ (inputID, propsToParse = {}) => {
+ const newRef = inputRefs.current[inputID] || propsToParse.ref || createRef();
+ if (inputRefs.current[inputID] !== newRef) {
+ inputRefs.current[inputID] = newRef;
+ }
- if (propsToParse.shouldSaveDraft) {
- FormActions.setDraftValues(formID, {[inputKey]: value});
- }
+ if (!_.isUndefined(propsToParse.value)) {
+ inputValues[inputID] = propsToParse.value;
+ } else if (propsToParse.shouldSaveDraft && !_.isUndefined(draftValues[inputID]) && _.isUndefined(inputValues[inputID])) {
+ inputValues[inputID] = draftValues[inputID];
+ } else if (propsToParse.shouldUseDefaultValue && _.isUndefined(inputValues[inputID])) {
+ // We force the form to set the input value from the defaultValue props if there is a saved valid value
+ inputValues[inputID] = propsToParse.defaultValue;
+ } else if (_.isUndefined(inputValues[inputID])) {
+ // We want to initialize the input value if it's undefined
+ inputValues[inputID] = _.isUndefined(propsToParse.defaultValue) ? getInitialValueByType(propsToParse.valueType) : propsToParse.defaultValue;
+ }
- if (_.isFunction(propsToParse.onValueChange)) {
- propsToParse.onValueChange(value, inputKey);
- }
- },
- };
- },
- [draftValues, formID, errors, formState, hasServerError, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange],
- );
- const value = useMemo(() => ({registerInput}), [registerInput]);
-
- return (
-
- {/* eslint-disable react/jsx-props-no-spreading */}
-
- {_.isFunction(children) ? children({inputValues}) : children}
-
-
- );
-}
+ const errorFields = lodashGet(formState, 'errorFields', {});
+ const fieldErrorMessage =
+ _.chain(errorFields[inputID])
+ .keys()
+ .sortBy()
+ .reverse()
+ .map((key) => errorFields[inputID][key])
+ .first()
+ .value() || '';
+
+ return {
+ ...propsToParse,
+ ref:
+ typeof propsToParse.ref === 'function'
+ ? (node) => {
+ propsToParse.ref(node);
+ newRef.current = node;
+ }
+ : newRef,
+ inputID,
+ key: propsToParse.key || inputID,
+ errorText: errors[inputID] || fieldErrorMessage,
+ value: inputValues[inputID],
+ // As the text input is controlled, we never set the defaultValue prop
+ // as this is already happening by the value prop.
+ defaultValue: undefined,
+ onTouched: (event) => {
+ if (!propsToParse.shouldSetTouchedOnBlurOnly) {
+ setTimeout(() => {
+ setTouchedInput(inputID);
+ }, VALIDATE_DELAY);
+ }
+ if (_.isFunction(propsToParse.onTouched)) {
+ propsToParse.onTouched(event);
+ }
+ },
+ onPress: (event) => {
+ if (!propsToParse.shouldSetTouchedOnBlurOnly) {
+ setTimeout(() => {
+ setTouchedInput(inputID);
+ }, VALIDATE_DELAY);
+ }
+ if (_.isFunction(propsToParse.onPress)) {
+ propsToParse.onPress(event);
+ }
+ },
+ onPressOut: (event) => {
+ // To prevent validating just pressed inputs, we need to set the touched input right after
+ // onValidate and to do so, we need to delays setTouchedInput of the same amount of time
+ // as the onValidate is delayed
+ if (!propsToParse.shouldSetTouchedOnBlurOnly) {
+ setTimeout(() => {
+ setTouchedInput(inputID);
+ }, VALIDATE_DELAY);
+ }
+ if (_.isFunction(propsToParse.onPressIn)) {
+ propsToParse.onPressIn(event);
+ }
+ },
+ onBlur: (event) => {
+ // Only run validation when user proactively blurs the input.
+ if (Visibility.isVisible() && Visibility.hasFocus()) {
+ const relatedTargetId = lodashGet(event, 'nativeEvent.relatedTarget.id');
+ // We delay the validation in order to prevent Checkbox loss of focus when
+ // the user is focusing a TextInput and proceeds to toggle a CheckBox in
+ // web and mobile web platforms.
+
+ setTimeout(() => {
+ if (
+ relatedTargetId &&
+ _.includes([CONST.OVERLAY.BOTTOM_BUTTON_NATIVE_ID, CONST.OVERLAY.TOP_BUTTON_NATIVE_ID, CONST.BACK_BUTTON_NATIVE_ID], relatedTargetId)
+ ) {
+ return;
+ }
+ setTouchedInput(inputID);
+ if (shouldValidateOnBlur) {
+ onValidate(inputValues, !hasServerError);
+ }
+ }, VALIDATE_DELAY);
+ }
+
+ if (_.isFunction(propsToParse.onBlur)) {
+ propsToParse.onBlur(event);
+ }
+ },
+ onInputChange: (value, key) => {
+ const inputKey = key || inputID;
+ setInputValues((prevState) => {
+ const newState = {
+ ...prevState,
+ [inputKey]: value,
+ };
+
+ if (shouldValidateOnChange) {
+ onValidate(newState);
+ }
+ return newState;
+ });
+
+ if (propsToParse.shouldSaveDraft) {
+ FormActions.setDraftValues(formID, {[inputKey]: value});
+ }
+
+ if (_.isFunction(propsToParse.onValueChange)) {
+ propsToParse.onValueChange(value, inputKey);
+ }
+ },
+ };
+ },
+ [draftValues, formID, errors, formState, hasServerError, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange],
+ );
+ const value = useMemo(() => ({registerInput}), [registerInput]);
+
+ return (
+
+ {/* eslint-disable react/jsx-props-no-spreading */}
+
+ {_.isFunction(children) ? children({inputValues}) : children}
+
+
+ );
+ },
+);
FormProvider.displayName = 'Form';
FormProvider.propTypes = propTypes;
diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js
index 638b6e5f8d19..da34262a8af8 100644
--- a/src/components/Form/FormWrapper.js
+++ b/src/components/Form/FormWrapper.js
@@ -8,9 +8,9 @@ import FormSubmit from '@components/FormSubmit';
import refPropTypes from '@components/refPropTypes';
import SafeAreaConsumer from '@components/SafeAreaConsumer';
import ScrollViewWithContext from '@components/ScrollViewWithContext';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import stylePropTypes from '@styles/stylePropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import errorsPropType from './errorsPropType';
const propTypes = {
diff --git a/src/components/FormAlertWithSubmitButton.js b/src/components/FormAlertWithSubmitButton.js
index b16a4d2a08ee..86e88c27b388 100644
--- a/src/components/FormAlertWithSubmitButton.js
+++ b/src/components/FormAlertWithSubmitButton.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Button from './Button';
import FormAlertWrapper from './FormAlertWrapper';
@@ -50,6 +50,12 @@ const propTypes = {
/** Styles for the button */
// eslint-disable-next-line react/forbid-prop-types
buttonStyles: PropTypes.arrayOf(PropTypes.object),
+
+ /** Whether to use a smaller submit button size */
+ useSmallerSubmitButtonSize: PropTypes.bool,
+
+ /** Style for the error message for submit button */
+ errorMessageStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
};
const defaultProps = {
@@ -62,8 +68,10 @@ const defaultProps = {
enabledWhenOffline: false,
disablePressOnEnter: false,
isSubmitActionDangerous: false,
+ useSmallerSubmitButtonSize: false,
footerContent: null,
buttonStyles: [],
+ errorMessageStyle: [],
};
function FormAlertWithSubmitButton(props) {
@@ -77,6 +85,7 @@ function FormAlertWithSubmitButton(props) {
isMessageHtml={props.isMessageHtml}
message={props.message}
onFixTheErrorsLinkPressed={props.onFixTheErrorsLinkPressed}
+ errorMessageStyle={props.errorMessageStyle}
>
{(isOffline) => (
@@ -87,6 +96,7 @@ function FormAlertWithSubmitButton(props) {
text={props.buttonText}
style={buttonStyles}
danger={props.isSubmitActionDangerous}
+ medium={props.useSmallerSubmitButtonSize}
/>
) : (
)}
{props.footerContent}
diff --git a/src/components/FormAlertWrapper.js b/src/components/FormAlertWrapper.js
index c577048c0a1b..6062ea8f7803 100644
--- a/src/components/FormAlertWrapper.js
+++ b/src/components/FormAlertWrapper.js
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import FormHelpMessage from './FormHelpMessage';
import networkPropTypes from './networkPropTypes';
import {withNetwork} from './OnyxProvider';
@@ -35,11 +35,15 @@ const propTypes = {
/** Callback fired when the "fix the errors" link is pressed */
onFixTheErrorsLinkPressed: PropTypes.func,
+ /** Style for the error message for submit button */
+ errorMessageStyle: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
+
...withLocalizePropTypes,
};
const defaultProps = {
containerStyles: [],
+ errorMessageStyle: [],
isAlertVisible: false,
isMessageHtml: false,
message: '',
@@ -74,7 +78,7 @@ function FormAlertWrapper(props) {
{props.isAlertVisible && (
{children}
diff --git a/src/components/FormHelpMessage.tsx b/src/components/FormHelpMessage.tsx
index 27a1f5827d75..43709b51db44 100644
--- a/src/components/FormHelpMessage.tsx
+++ b/src/components/FormHelpMessage.tsx
@@ -1,9 +1,9 @@
import isEmpty from 'lodash/isEmpty';
import React from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Localize from '@libs/Localize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import Text from './Text';
@@ -20,9 +20,12 @@ type FormHelpMessageProps = {
/** Container style props */
style?: StyleProp;
+
+ /** Whether to show dot indicator */
+ shouldShowRedDotIndicator?: boolean;
};
-function FormHelpMessage({message = '', children, isError = true, style}: FormHelpMessageProps) {
+function FormHelpMessage({message = '', children, isError = true, style, shouldShowRedDotIndicator = true}: FormHelpMessageProps) {
const theme = useTheme();
const styles = useThemeStyles();
if (isEmpty(message) && isEmpty(children)) {
@@ -33,13 +36,15 @@ function FormHelpMessage({message = '', children, isError = true, style}: FormHe
return (
- {isError && (
+ {isError && shouldShowRedDotIndicator && (
)}
- {children ?? {translatedMessage}}
+
+ {children ?? {translatedMessage}}
+
);
}
diff --git a/src/components/FormScrollView.tsx b/src/components/FormScrollView.tsx
index c2f01e1d0511..4646a534e750 100644
--- a/src/components/FormScrollView.tsx
+++ b/src/components/FormScrollView.tsx
@@ -1,6 +1,6 @@
import React, {ForwardedRef} from 'react';
import {ScrollView, ScrollViewProps} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
type FormScrollViewProps = ScrollViewProps & {
/** Form elements */
diff --git a/src/components/FullscreenLoadingIndicator.tsx b/src/components/FullscreenLoadingIndicator.tsx
index fc0687f6da18..2b5f7b3ada72 100644
--- a/src/components/FullscreenLoadingIndicator.tsx
+++ b/src/components/FullscreenLoadingIndicator.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {ActivityIndicator, StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
type FullScreenLoadingIndicatorProps = {
style?: StyleProp;
diff --git a/src/components/GrowlNotification/GrowlNotificationContainer/index.js b/src/components/GrowlNotification/GrowlNotificationContainer/index.js
index 82672edb14c2..ccc404d415d7 100644
--- a/src/components/GrowlNotification/GrowlNotificationContainer/index.js
+++ b/src/components/GrowlNotification/GrowlNotificationContainer/index.js
@@ -1,7 +1,7 @@
import React from 'react';
import {Animated} from 'react-native';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import growlNotificationContainerPropTypes from './growlNotificationContainerPropTypes';
const propTypes = {
diff --git a/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js b/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js
index 457a9dce66d9..207033f8fac2 100644
--- a/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js
+++ b/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js
@@ -1,8 +1,8 @@
import React from 'react';
import {Animated} from 'react-native';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import growlNotificationContainerPropTypes from './growlNotificationContainerPropTypes';
const propTypes = {
diff --git a/src/components/GrowlNotification/index.js b/src/components/GrowlNotification/index.js
index faf1ec9cfa16..bcb4a8703b94 100644
--- a/src/components/GrowlNotification/index.js
+++ b/src/components/GrowlNotification/index.js
@@ -5,10 +5,10 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Pressables from '@components/Pressable';
import Text from '@components/Text';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Growl from '@libs/Growl';
import useNativeDriver from '@libs/useNativeDriver';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import GrowlNotificationContainer from './GrowlNotificationContainer';
diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
index 9a2d7c673c5b..86ddf0a52bb3 100755
--- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
+++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
import React, {useMemo} from 'react';
import {defaultHTMLElementModels, RenderHTMLConfigProvider, TRenderEngineProvider} from 'react-native-render-html';
import _ from 'underscore';
+import useThemeStyles from '@hooks/useThemeStyles';
import convertToLTR from '@libs/convertToLTR';
-import singleFontFamily from '@styles/fontFamily/singleFontFamily';
-import useThemeStyles from '@styles/useThemeStyles';
+import singleFontFamily from '@styles/utils/fontFamily/singleFontFamily';
import * as HTMLEngineUtils from './htmlEngineUtils';
import htmlRenderers from './HTMLRenderers';
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
index 49642308a357..8fd907470c19 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js
@@ -6,8 +6,8 @@ import AnchorForCommentsOnly from '@components/AnchorForCommentsOnly';
import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils';
import Text from '@components/Text';
import useEnvironment from '@hooks/useEnvironment';
+import useThemeStyles from '@hooks/useThemeStyles';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
import htmlRendererPropTypes from './htmlRendererPropTypes';
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/CodeRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/CodeRenderer.js
index 9d101b8a5190..1932eaaf8a4f 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/CodeRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/CodeRenderer.js
@@ -3,7 +3,7 @@ import {splitBoxModelStyle} from 'react-native-render-html';
import _ from 'underscore';
import * as HTMLEngineUtils from '@components/HTMLEngineProvider/htmlEngineUtils';
import InlineCodeBlock from '@components/InlineCodeBlock';
-import useStyleUtils from '@styles/useStyleUtils';
+import useStyleUtils from '@hooks/useStyleUtils';
import htmlRendererPropTypes from './htmlRendererPropTypes';
function CodeRenderer(props) {
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js
index e97d01808a6e..9ff5fdecae13 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js
@@ -2,9 +2,8 @@ import React from 'react';
import _ from 'underscore';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import editedLabelStyles from '@styles/editedLabelStyles';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import htmlRendererPropTypes from './htmlRendererPropTypes';
@@ -32,7 +31,7 @@ function EditedRenderer(props) {
{...defaultRendererProps}
fontSize={variables.fontSizeSmall}
color={theme.textSupporting}
- style={[editedLabelStyles, isPendingDelete && styles.offlineFeedback.deleted]}
+ style={[styles.editedLabelStyles, isPendingDelete && styles.offlineFeedback.deleted]}
>
{props.translate('reportActionCompose.edited')}
diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
index 7cbdf8d69831..05016a25394a 100644
--- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
+++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js
@@ -5,10 +5,10 @@ import PressableWithoutFocus from '@components/Pressable/PressableWithoutFocus';
import {ShowContextMenuContext, showContextMenuForReport} from '@components/ShowContextMenuContext';
import ThumbnailImage from '@components/ThumbnailImage';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -77,7 +77,7 @@ function ImageRenderer(props) {
ReportUtils.isArchivedRoom(report),
)
}
- role={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
+ accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={translate('accessibilityHints.viewAttachment')}
>
{
onPressIn={props.onPressIn}
onPressOut={props.onPressOut}
onLongPress={(event) => showContextMenuForReport(event, anchor, report.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
accessibilityLabel={props.translate('accessibilityHints.prestyledText')}
>
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 46fe1a25c920..c02f21d7c6f2 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -1,6 +1,6 @@
import React, {ReactElement} from 'react';
import {StyleProp, TextStyle, View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import EnvironmentBadge from './EnvironmentBadge';
import Text from './Text';
diff --git a/src/components/HeaderGap/index.desktop.js b/src/components/HeaderGap/index.desktop.js
deleted file mode 100644
index 07ea1ea6f48d..000000000000
--- a/src/components/HeaderGap/index.desktop.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import PropTypes from 'prop-types';
-import React, {memo} from 'react';
-import {View} from 'react-native';
-import withThemeStyles, {withThemeStylesPropTypes} from '@components/withThemeStyles';
-import compose from '@libs/compose';
-
-const propTypes = {
- /** Styles to apply to the HeaderGap */
- // eslint-disable-next-line react/forbid-prop-types
- styles: PropTypes.arrayOf(PropTypes.object),
- ...withThemeStylesPropTypes,
-};
-
-const defaultProps = {
- styles: [],
-};
-
-function HeaderGap(props) {
- return ;
-}
-
-HeaderGap.displayName = 'HeaderGap';
-HeaderGap.propTypes = propTypes;
-HeaderGap.defaultProps = defaultProps;
-export default compose(memo, withThemeStyles)(HeaderGap);
diff --git a/src/components/HeaderGap/index.desktop.tsx b/src/components/HeaderGap/index.desktop.tsx
new file mode 100644
index 000000000000..3687bb2e6b02
--- /dev/null
+++ b/src/components/HeaderGap/index.desktop.tsx
@@ -0,0 +1,13 @@
+import React, {memo} from 'react';
+import {View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type {HeaderGapProps, HeaderGapReturnType} from './types';
+
+function HeaderGap({styles}: HeaderGapProps): HeaderGapReturnType {
+ const themeStyles = useThemeStyles();
+ return ;
+}
+
+HeaderGap.displayName = 'HeaderGap';
+
+export default memo(HeaderGap);
diff --git a/src/components/HeaderGap/index.js b/src/components/HeaderGap/index.js
deleted file mode 100644
index 35e6bf92fb5d..000000000000
--- a/src/components/HeaderGap/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-function HeaderGap() {
- return null;
-}
-
-HeaderGap.displayName = 'HeaderGap';
-export default HeaderGap;
diff --git a/src/components/HeaderGap/index.tsx b/src/components/HeaderGap/index.tsx
new file mode 100644
index 000000000000..191923efd7c8
--- /dev/null
+++ b/src/components/HeaderGap/index.tsx
@@ -0,0 +1,10 @@
+import type {HeaderGapProps, HeaderGapReturnType} from './types';
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function HeaderGap({styles}: HeaderGapProps): HeaderGapReturnType {
+ return null;
+}
+
+HeaderGap.displayName = 'HeaderGap';
+
+export default HeaderGap;
diff --git a/src/components/HeaderGap/types.ts b/src/components/HeaderGap/types.ts
new file mode 100644
index 000000000000..55a202c2e48c
--- /dev/null
+++ b/src/components/HeaderGap/types.ts
@@ -0,0 +1,10 @@
+import {ReactNode} from 'react';
+import {StyleProp, ViewStyle} from 'react-native';
+
+type HeaderGapProps = {
+ styles?: StyleProp;
+};
+
+type HeaderGapReturnType = ReactNode;
+
+export type {HeaderGapProps, HeaderGapReturnType};
diff --git a/src/components/HeaderPageLayout.js b/src/components/HeaderPageLayout.js
index 27c9656abd1a..9ef5d4f83a06 100644
--- a/src/components/HeaderPageLayout.js
+++ b/src/components/HeaderPageLayout.js
@@ -3,11 +3,11 @@ import React, {useMemo} from 'react';
import {ScrollView, View} from 'react-native';
import _ from 'underscore';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import FixedFooter from './FixedFooter';
import HeaderWithBackButton from './HeaderWithBackButton';
import headerWithBackButtonPropTypes from './HeaderWithBackButton/headerWithBackButtonPropTypes';
diff --git a/src/components/HeaderWithBackButton/index.js b/src/components/HeaderWithBackButton/index.js
index aa73ab2d3327..5c76d1665310 100755
--- a/src/components/HeaderWithBackButton/index.js
+++ b/src/components/HeaderWithBackButton/index.js
@@ -10,12 +10,12 @@ import ThreeDotsMenu from '@components/ThreeDotsMenu';
import Tooltip from '@components/Tooltip';
import useKeyboardState from '@hooks/useKeyboardState';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import useThrottledButtonState from '@hooks/useThrottledButtonState';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
import getButtonState from '@libs/getButtonState';
import Navigation from '@libs/Navigation/Navigation';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import headerWithBackButtonPropTypes from './headerWithBackButtonPropTypes';
@@ -141,7 +141,7 @@ function HeaderWithBackButton({
Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID))))}
+ onPress={singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID, Navigation.getActiveRoute()))))}
style={[styles.touchableButtonImage]}
role="button"
accessibilityLabel={translate('getAssistancePage.questionMarkButtonTooltip')}
@@ -168,7 +168,7 @@ function HeaderWithBackButton({
policy);
- const cleanAllPolicyMembers = _.pick(props.allPolicyMembers, (policyMembers) => policyMembers);
-
- const paymentCardList = props.fundList || {};
-
- // All of the error & info-checking methods are put into an array. This is so that using _.some() will return
- // early as soon as the first error / info condition is returned. This makes the checks very efficient since
- // we only care if a single error / info condition exists anywhere.
- const errorCheckingMethods = [
- () => !_.isEmpty(props.userWallet.errors),
- () => PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList),
- () => _.some(cleanPolicies, PolicyUtils.hasPolicyError),
- () => _.some(cleanPolicies, PolicyUtils.hasCustomUnitsError),
- () => _.some(cleanAllPolicyMembers, PolicyUtils.hasPolicyMemberError),
- () => !_.isEmpty(props.reimbursementAccount.errors),
- () => UserUtils.hasLoginListError(props.loginList),
-
- // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
- () => !_.isEmpty(props.walletTerms.errors) && !props.walletTerms.chatReportID,
- ];
- const infoCheckingMethods = [() => UserUtils.hasLoginListInfo(props.loginList)];
- const shouldShowErrorIndicator = _.some(errorCheckingMethods, (errorCheckingMethod) => errorCheckingMethod());
- const shouldShowInfoIndicator = !shouldShowErrorIndicator && _.some(infoCheckingMethods, (infoCheckingMethod) => infoCheckingMethod());
-
- const indicatorColor = shouldShowErrorIndicator ? theme.danger : theme.success;
- const indicatorStyles = [styles.alignItemsCenter, styles.justifyContentCenter, styles.statusIndicator(indicatorColor)];
-
- return (shouldShowErrorIndicator || shouldShowInfoIndicator) && ;
-}
-
-Indicator.defaultProps = defaultProps;
-Indicator.propTypes = propTypes;
-Indicator.displayName = 'Indicator';
-
-export default withOnyx({
- allPolicyMembers: {
- key: ONYXKEYS.COLLECTION.POLICY_MEMBERS,
- },
- policies: {
- key: ONYXKEYS.COLLECTION.POLICY,
- },
- bankAccountList: {
- key: ONYXKEYS.BANK_ACCOUNT_LIST,
- },
- reimbursementAccount: {
- key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
- },
- fundList: {
- key: ONYXKEYS.FUND_LIST,
- },
- userWallet: {
- key: ONYXKEYS.USER_WALLET,
- },
- walletTerms: {
- key: ONYXKEYS.WALLET_TERMS,
- },
- loginList: {
- key: ONYXKEYS.LOGIN_LIST,
- },
-})(Indicator);
diff --git a/src/components/Indicator.tsx b/src/components/Indicator.tsx
new file mode 100644
index 000000000000..7b7eae97fd86
--- /dev/null
+++ b/src/components/Indicator.tsx
@@ -0,0 +1,104 @@
+import React from 'react';
+import {StyleSheet, View} from 'react-native';
+import {OnyxCollection, withOnyx} from 'react-native-onyx';
+import {OnyxEntry} from 'react-native-onyx/lib/types';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import * as PolicyUtils from '@libs/PolicyUtils';
+import * as UserUtils from '@libs/UserUtils';
+import * as PaymentMethods from '@userActions/PaymentMethods';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {BankAccountList, FundList, LoginList, Policy, PolicyMembers, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx';
+
+type CheckingMethod = () => boolean;
+
+type IndicatorOnyxProps = {
+ /** The employee list of all policies (coming from Onyx) */
+ allPolicyMembers: OnyxCollection;
+
+ /** All the user's policies (from Onyx via withFullPolicy) */
+ policies: OnyxCollection;
+
+ /** List of bank accounts */
+ bankAccountList: OnyxEntry;
+
+ /** List of user cards */
+ fundList: OnyxEntry;
+
+ /** The user's wallet (coming from Onyx) */
+ userWallet: OnyxEntry;
+
+ /** Bank account attached to free plan */
+ reimbursementAccount: OnyxEntry;
+
+ /** Information about the user accepting the terms for payments */
+ walletTerms: OnyxEntry;
+
+ /** Login list for the user that is signed in */
+ loginList: OnyxEntry;
+};
+
+type IndicatorProps = IndicatorOnyxProps;
+
+function Indicator({reimbursementAccount, allPolicyMembers, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) {
+ const theme = useTheme();
+ const styles = useThemeStyles();
+
+ // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and
+ // those should be cleaned out before doing any error checking
+ const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => !!policy));
+ const cleanAllPolicyMembers = Object.fromEntries(Object.entries(allPolicyMembers ?? {}).filter(([, policyMembers]) => !!policyMembers));
+
+ // All of the error & info-checking methods are put into an array. This is so that using _.some() will return
+ // early as soon as the first error / info condition is returned. This makes the checks very efficient since
+ // we only care if a single error / info condition exists anywhere.
+ const errorCheckingMethods: CheckingMethod[] = [
+ () => Object.keys(userWallet?.errors ?? {}).length > 0,
+ () => PaymentMethods.hasPaymentMethodError(bankAccountList, fundList),
+ () => Object.values(cleanPolicies).some(PolicyUtils.hasPolicyError),
+ () => Object.values(cleanPolicies).some(PolicyUtils.hasCustomUnitsError),
+ () => Object.values(cleanAllPolicyMembers).some(PolicyUtils.hasPolicyMemberError),
+ () => Object.keys(reimbursementAccount?.errors ?? {}).length > 0,
+ () => !!loginList && UserUtils.hasLoginListError(loginList),
+
+ // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
+ () => Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID,
+ ];
+ const infoCheckingMethods: CheckingMethod[] = [() => !!loginList && UserUtils.hasLoginListInfo(loginList)];
+ const shouldShowErrorIndicator = errorCheckingMethods.some((errorCheckingMethod) => errorCheckingMethod());
+ const shouldShowInfoIndicator = !shouldShowErrorIndicator && infoCheckingMethods.some((infoCheckingMethod) => infoCheckingMethod());
+
+ const indicatorColor = shouldShowErrorIndicator ? theme.danger : theme.success;
+ const indicatorStyles = [styles.alignItemsCenter, styles.justifyContentCenter, styles.statusIndicator(indicatorColor)];
+
+ return (shouldShowErrorIndicator || shouldShowInfoIndicator) && ;
+}
+
+Indicator.displayName = 'Indicator';
+
+export default withOnyx({
+ allPolicyMembers: {
+ key: ONYXKEYS.COLLECTION.POLICY_MEMBERS,
+ },
+ policies: {
+ key: ONYXKEYS.COLLECTION.POLICY,
+ },
+ bankAccountList: {
+ key: ONYXKEYS.BANK_ACCOUNT_LIST,
+ },
+ reimbursementAccount: {
+ key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
+ },
+ fundList: {
+ key: ONYXKEYS.FUND_LIST,
+ },
+ userWallet: {
+ key: ONYXKEYS.USER_WALLET,
+ },
+ walletTerms: {
+ key: ONYXKEYS.WALLET_TERMS,
+ },
+ loginList: {
+ key: ONYXKEYS.LOGIN_LIST,
+ },
+})(Indicator);
diff --git a/src/components/InlineCodeBlock/WrappedText.js b/src/components/InlineCodeBlock/WrappedText.js
deleted file mode 100644
index f00ec891116b..000000000000
--- a/src/components/InlineCodeBlock/WrappedText.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import PropTypes from 'prop-types';
-import React, {Fragment} from 'react';
-import {View} from 'react-native';
-import _ from 'underscore';
-import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
-import CONST from '@src/CONST';
-
-/**
- * Breaks the text into matrix
- * for eg: My Name is Rajat
- * [
- * [My,' ',Name,' ',' ',is,' ',Rajat],
- * ]
- *
- * @param {String} text
- * @returns {Array}
- */
-function getTextMatrix(text) {
- return _.map(text.split('\n'), (row) => _.without(row.split(CONST.REGEX.SPACE_OR_EMOJI), ''));
-}
-
-const propTypes = {
- /** Required text */
- children: PropTypes.string.isRequired,
-
- /** Style to be applied to Text */
- // eslint-disable-next-line react/forbid-prop-types
- textStyles: PropTypes.arrayOf(PropTypes.object),
-
- /** Style for each word(Token) in the text, remember that token also includes whitespaces among words */
- // eslint-disable-next-line react/forbid-prop-types
- wordStyles: PropTypes.arrayOf(PropTypes.object),
-};
-
-const defaultProps = {
- textStyles: [],
- wordStyles: [],
-};
-
-function WrappedText(props) {
- const styles = useThemeStyles();
- if (!_.isString(props.children)) {
- return null;
- }
-
- const textMatrix = getTextMatrix(props.children);
- return (
- <>
- {_.map(textMatrix, (rowText, rowIndex) => (
-
- {_.map(rowText, (colText, colIndex) => (
- // Outer View is important to vertically center the Text
-
-
- {colText}
-
-
- ))}
-
- ))}
- >
- );
-}
-
-WrappedText.propTypes = propTypes;
-WrappedText.defaultProps = defaultProps;
-WrappedText.displayName = 'WrappedText';
-
-export default WrappedText;
diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx
new file mode 100644
index 000000000000..f0bb4e3ffd53
--- /dev/null
+++ b/src/components/InlineCodeBlock/WrappedText.tsx
@@ -0,0 +1,66 @@
+import React, {Fragment} from 'react';
+import {StyleProp, TextStyle, View, ViewStyle} from 'react-native';
+import Text from '@components/Text';
+import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
+import type ChildrenProps from '@src/types/utils/ChildrenProps';
+
+type WrappedTextProps = ChildrenProps & {
+ /** Style to be applied to Text */
+ textStyles?: StyleProp;
+
+ /**
+ * Style for each individual word (token) in the text. Note that a token can also include whitespace characters between words.
+ */
+ wordStyles?: StyleProp;
+};
+
+/**
+ * Breaks the text into matrix
+ *
+ * @example
+ * const text = "My Name is Rajat";
+ * const resultMatrix = getTextMatrix(text);
+ * console.log(resultMatrix);
+ * // Output:
+ * // [
+ * // ['My', ' ', 'Name', ' ', 'is', ' ', 'Rajat'],
+ * // ]
+ */
+function getTextMatrix(text: string): string[][] {
+ return text.split('\n').map((row) => row.split(CONST.REGEX.SPACE_OR_EMOJI).filter((value) => value !== ''));
+}
+
+function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) {
+ const styles = useThemeStyles();
+
+ if (typeof children !== 'string') {
+ return null;
+ }
+
+ const textMatrix = getTextMatrix(children);
+
+ return textMatrix.map((rowText, rowIndex) => (
+
+ {rowText.map((colText, colIndex) => (
+ // Outer View is important to vertically center the Text
+
+
+ {colText}
+
+
+ ))}
+
+ ));
+}
+
+WrappedText.displayName = 'WrappedText';
+
+export default WrappedText;
diff --git a/src/components/InlineCodeBlock/index.js b/src/components/InlineCodeBlock/index.js
deleted file mode 100644
index 84666931d9b2..000000000000
--- a/src/components/InlineCodeBlock/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import Text from '@components/Text';
-import inlineCodeBlockPropTypes from './inlineCodeBlockPropTypes';
-
-function InlineCodeBlock(props) {
- const TDefaultRenderer = props.TDefaultRenderer;
- const textStyles = _.omit(props.textStyle, 'textDecorationLine');
-
- return (
-
- {props.defaultRendererProps.tnode.data}
-
- );
-}
-
-InlineCodeBlock.propTypes = inlineCodeBlockPropTypes;
-InlineCodeBlock.displayName = 'InlineCodeBlock';
-export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/index.native.js b/src/components/InlineCodeBlock/index.native.js
deleted file mode 100644
index 983463222532..000000000000
--- a/src/components/InlineCodeBlock/index.native.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import useThemeStyles from '@styles/useThemeStyles';
-import inlineCodeBlockPropTypes from './inlineCodeBlockPropTypes';
-import WrappedText from './WrappedText';
-
-function InlineCodeBlock(props) {
- const styles = useThemeStyles();
- const TDefaultRenderer = props.TDefaultRenderer;
- return (
-
-
- {props.defaultRendererProps.tnode.data}
-
-
- );
-}
-
-InlineCodeBlock.propTypes = inlineCodeBlockPropTypes;
-InlineCodeBlock.displayName = 'InlineCodeBlock';
-export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/index.native.tsx b/src/components/InlineCodeBlock/index.native.tsx
new file mode 100644
index 000000000000..3a70308fa0cc
--- /dev/null
+++ b/src/components/InlineCodeBlock/index.native.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import type {TText} from 'react-native-render-html';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type InlineCodeBlockProps from './types';
+import WrappedText from './WrappedText';
+
+function InlineCodeBlock({TDefaultRenderer, defaultRendererProps, textStyle, boxModelStyle}: InlineCodeBlockProps) {
+ const styles = useThemeStyles();
+
+ return (
+
+
+ {defaultRendererProps.tnode.data}
+
+
+ );
+}
+
+InlineCodeBlock.displayName = 'InlineCodeBlock';
+
+export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/index.tsx b/src/components/InlineCodeBlock/index.tsx
new file mode 100644
index 000000000000..0802d4752661
--- /dev/null
+++ b/src/components/InlineCodeBlock/index.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import {StyleSheet} from 'react-native';
+import type {TText} from 'react-native-render-html';
+import Text from '@components/Text';
+import type InlineCodeBlockProps from './types';
+
+function InlineCodeBlock({TDefaultRenderer, textStyle, defaultRendererProps, boxModelStyle}: InlineCodeBlockProps) {
+ const flattenTextStyle = StyleSheet.flatten(textStyle);
+ const {textDecorationLine, ...textStyles} = flattenTextStyle;
+
+ return (
+
+ {defaultRendererProps.tnode.data}
+
+ );
+}
+
+InlineCodeBlock.displayName = 'InlineCodeBlock';
+
+export default InlineCodeBlock;
diff --git a/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js b/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js
deleted file mode 100644
index e8430d17d849..000000000000
--- a/src/components/InlineCodeBlock/inlineCodeBlockPropTypes.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import PropTypes from 'prop-types';
-
-const inlineCodeBlockPropTypes = {
- TDefaultRenderer: PropTypes.func.isRequired,
- defaultRendererProps: PropTypes.object.isRequired,
- boxModelStyle: PropTypes.any.isRequired,
- textStyle: PropTypes.any.isRequired,
-};
-
-export default inlineCodeBlockPropTypes;
diff --git a/src/components/InlineCodeBlock/types.ts b/src/components/InlineCodeBlock/types.ts
new file mode 100644
index 000000000000..a100177e41a7
--- /dev/null
+++ b/src/components/InlineCodeBlock/types.ts
@@ -0,0 +1,11 @@
+import {StyleProp, TextStyle, ViewStyle} from 'react-native';
+import type {TDefaultRenderer, TDefaultRendererProps, TText} from 'react-native-render-html';
+
+type InlineCodeBlockProps = {
+ TDefaultRenderer: TDefaultRenderer;
+ textStyle: StyleProp;
+ defaultRendererProps: TDefaultRendererProps;
+ boxModelStyle: StyleProp;
+};
+
+export default InlineCodeBlockProps;
diff --git a/src/components/InlineSystemMessage.tsx b/src/components/InlineSystemMessage.tsx
index 6e6423a19a35..bef4c21289d5 100644
--- a/src/components/InlineSystemMessage.tsx
+++ b/src/components/InlineSystemMessage.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import Text from './Text';
diff --git a/src/components/InvertedFlatList/index.native.js b/src/components/InvertedFlatList/index.native.js
index d52d5a6d08f7..59810cba62c4 100644
--- a/src/components/InvertedFlatList/index.native.js
+++ b/src/components/InvertedFlatList/index.native.js
@@ -1,5 +1,5 @@
import React, {forwardRef} from 'react';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import BaseInvertedFlatList from './BaseInvertedFlatList';
import CellRendererComponent from './CellRendererComponent';
diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js
index e229a860dd9f..e9eb1e4c54c8 100644
--- a/src/components/KYCWall/BaseKYCWall.js
+++ b/src/components/KYCWall/BaseKYCWall.js
@@ -4,6 +4,7 @@ import {Dimensions} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu';
+import * as BankAccounts from '@libs/actions/BankAccounts';
import getClickedTargetLocation from '@libs/getClickedTargetLocation';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
@@ -118,7 +119,7 @@ function KYCWall({
const selectPaymentMethod = (paymentMethod) => {
onSelectPaymentMethod(paymentMethod);
if (paymentMethod === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) {
- Navigation.navigate(addBankAccountRoute);
+ BankAccounts.openPersonalBankAccountSetupView();
} else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) {
Navigation.navigate(addDebitCardRoute);
} else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) {
diff --git a/src/components/LHNOptionsList/LHNOptionsList.js b/src/components/LHNOptionsList/LHNOptionsList.js
index 8febd7f247d6..71b14b6fadcd 100644
--- a/src/components/LHNOptionsList/LHNOptionsList.js
+++ b/src/components/LHNOptionsList/LHNOptionsList.js
@@ -8,13 +8,13 @@ import _ from 'underscore';
import participantPropTypes from '@components/participantPropTypes';
import transactionPropTypes from '@components/transactionPropTypes';
import withCurrentReportID, {withCurrentReportIDDefaultProps, withCurrentReportIDPropTypes} from '@components/withCurrentReportID';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
import stylePropTypes from '@styles/stylePropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js
index 053f201ac109..9e50c4b1690a 100644
--- a/src/components/LHNOptionsList/OptionRowLHN.js
+++ b/src/components/LHNOptionsList/OptionRowLHN.js
@@ -15,6 +15,9 @@ import SubscriptAvatar from '@components/SubscriptAvatar';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import DateUtils from '@libs/DateUtils';
import DomUtils from '@libs/DomUtils';
@@ -24,9 +27,6 @@ import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManag
import * as ReportUtils from '@libs/ReportUtils';
import * as ContextMenuActions from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -208,7 +208,7 @@ function OptionRowLHN(props) {
props.isFocused ? styles.sidebarLinkActive : null,
(hovered || isContextMenuActive) && !props.isFocused ? props.hoverStyle || styles.sidebarLinkHover : null,
]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('accessibilityHints.navigatesToChat')}
needsOffscreenAlphaCompositing={props.optionItem.icons.length >= 2}
>
diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx
index c04b0131744f..46adb1a4895e 100644
--- a/src/components/LocalePicker.tsx
+++ b/src/components/LocalePicker.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as App from '@userActions/App';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js b/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
index a86cb8bd7bd9..14601c7c4ba2 100644
--- a/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
+++ b/src/components/LocationErrorMessage/BaseLocationErrorMessage.js
@@ -8,9 +8,9 @@ import Text from '@components/Text';
import TextLink from '@components/TextLink';
import Tooltip from '@components/Tooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import colors from '@styles/colors';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
+import colors from '@styles/theme/colors';
import CONST from '@src/CONST';
import * as locationErrorMessagePropTypes from './locationErrorMessagePropTypes';
@@ -64,7 +64,7 @@ function BaseLocationErrorMessage({onClose, onAllowLocationLinkPress, locationEr
onPress={onClose}
onMouseDown={(e) => e.preventDefault()}
style={[styles.touchableButtonImage]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.close')}
>
diff --git a/src/components/Lottie/Lottie.tsx b/src/components/Lottie/Lottie.tsx
index 868eaf8cb95e..2bf7df056c4d 100644
--- a/src/components/Lottie/Lottie.tsx
+++ b/src/components/Lottie/Lottie.tsx
@@ -3,7 +3,7 @@ import React, {ForwardedRef, forwardRef} from 'react';
import {View} from 'react-native';
import DotLottieAnimation from '@components/LottieAnimations/types';
import useNetwork from '@hooks/useNetwork';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
type Props = {
source: DotLottieAnimation;
diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js
index 91430602a115..55a65237a691 100644
--- a/src/components/MagicCodeInput.js
+++ b/src/components/MagicCodeInput.js
@@ -4,10 +4,10 @@ import {StyleSheet, View} from 'react-native';
import {TapGestureHandler} from 'react-native-gesture-handler';
import _ from 'underscore';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import FormHelpMessage from './FormHelpMessage';
import networkPropTypes from './networkPropTypes';
diff --git a/src/components/MapView/Direction.tsx b/src/components/MapView/Direction.tsx
index ca4b26f2f2db..b3162149a48d 100644
--- a/src/components/MapView/Direction.tsx
+++ b/src/components/MapView/Direction.tsx
@@ -1,5 +1,5 @@
import Mapbox from '@rnmapbox/maps';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import {DirectionProps} from './MapViewTypes';
function Direction({coordinates}: DirectionProps) {
diff --git a/src/components/MapView/Direction.website.tsx b/src/components/MapView/Direction.website.tsx
index 9e5af2aa2b1d..f85bda125473 100644
--- a/src/components/MapView/Direction.website.tsx
+++ b/src/components/MapView/Direction.website.tsx
@@ -5,7 +5,7 @@
import React from 'react';
import {Layer, Source} from 'react-map-gl';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import {DirectionProps} from './MapViewTypes';
function Direction({coordinates}: DirectionProps) {
diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx
index 91f9d9930079..7b3d73479dde 100644
--- a/src/components/MapView/MapView.tsx
+++ b/src/components/MapView/MapView.tsx
@@ -3,10 +3,10 @@ import Mapbox, {MapState, MarkerView, setAccessToken} from '@rnmapbox/maps';
import {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
+import useThemeStyles from '@hooks/useThemeStyles';
import setUserLocation from '@libs/actions/UserLocation';
import compose from '@libs/compose';
import getCurrentPosition from '@libs/getCurrentPosition';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import useLocalize from '@src/hooks/useLocalize';
import useNetwork from '@src/hooks/useNetwork';
diff --git a/src/components/MapView/MapView.website.tsx b/src/components/MapView/MapView.website.tsx
index ecdb62efbe15..7910d7f93a29 100644
--- a/src/components/MapView/MapView.website.tsx
+++ b/src/components/MapView/MapView.website.tsx
@@ -9,9 +9,9 @@ import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useState
import Map, {MapRef, Marker} from 'react-map-gl';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import setUserLocation from '@userActions/UserLocation';
import CONST from '@src/CONST';
import useLocalize from '@src/hooks/useLocalize';
diff --git a/src/components/MapView/PendingMapView.tsx b/src/components/MapView/PendingMapView.tsx
index 2acdb59d3782..0af816785e9a 100644
--- a/src/components/MapView/PendingMapView.tsx
+++ b/src/components/MapView/PendingMapView.tsx
@@ -4,7 +4,7 @@ import {View} from 'react-native';
import BlockingView from '@components/BlockingViews/BlockingView';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import {PendingMapViewProps} from './MapViewTypes';
diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx
index b42540bacb13..f1daaaa229be 100644
--- a/src/components/MentionSuggestions.tsx
+++ b/src/components/MentionSuggestions.tsx
@@ -1,9 +1,9 @@
import React, {useCallback} from 'react';
import {View} from 'react-native';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import getStyledTextArray from '@libs/GetStyledTextArray';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {Icon} from '@src/types/onyx/OnyxCommon';
import AutoCompleteSuggestions from './AutoCompleteSuggestions';
diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index 0e07fcd22b4c..b1f6b7f7319a 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -2,20 +2,21 @@ import ExpensiMark from 'expensify-common/lib/ExpensiMark';
import React, {useEffect, useMemo} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import ControlSelection from '@libs/ControlSelection';
import convertToLTR from '@libs/convertToLTR';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import getButtonState from '@libs/getButtonState';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import Avatar from './Avatar';
import Badge from './Badge';
import DisplayNames from './DisplayNames';
+import FormHelpMessage from './FormHelpMessage';
import Hoverable from './Hoverable';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
@@ -106,6 +107,7 @@ const MenuItem = React.forwardRef((props, ref) => {
props.interactive && props.disabled ? {...styles.userSelectNone} : undefined,
styles.ltr,
isDeleted ? styles.offlineFeedback.deleted : undefined,
+ props.titleTextStyle,
],
props.titleStyle,
);
@@ -180,6 +182,8 @@ const MenuItem = React.forwardRef((props, ref) => {
onPressOut={ControlSelection.unblock}
onSecondaryInteraction={props.onSecondaryInteraction}
style={({pressed}) => [
+ props.containerStyle,
+ props.errorText ? styles.pb5 : {},
style,
!props.interactive && styles.cursorDefault,
StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive), true),
@@ -189,7 +193,7 @@ const MenuItem = React.forwardRef((props, ref) => {
]}
disabled={props.disabled}
ref={ref}
- role={CONST.ACCESSIBILITY_ROLE.MENUITEM}
+ role={CONST.ROLE.MENUITEM}
accessibilityLabel={props.title ? props.title.toString() : ''}
>
{({pressed}) => (
@@ -385,6 +389,14 @@ const MenuItem = React.forwardRef((props, ref) => {
{props.shouldShowRightComponent && props.rightComponent}
{props.shouldShowSelectedState && }
+ {Boolean(props.errorText) && (
+
+ )}
>
)}
diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx
index 02b78942dfcf..e019bd1aef30 100644
--- a/src/components/MessagesRow.tsx
+++ b/src/components/MessagesRow.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Localize from '@libs/Localize';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import DotIndicatorMessage from './DotIndicatorMessage';
@@ -48,7 +48,7 @@ function MessagesRow({messages = {}, type, onClose = () => {}, containerStyles,
diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx
index 1ea284b55280..89640c56f5ef 100644
--- a/src/components/Modal/BaseModal.tsx
+++ b/src/components/Modal/BaseModal.tsx
@@ -4,12 +4,12 @@ import ReactNativeModal from 'react-native-modal';
import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import usePrevious from '@hooks/usePrevious';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import ComposerFocusManager from '@libs/ComposerFocusManager';
import useNativeDriver from '@libs/useNativeDriver';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as Modal from '@userActions/Modal';
import CONST from '@src/CONST';
diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index bfc899f9c278..4269420dcd7f 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -1,8 +1,8 @@
import React, {useState} from 'react';
import withWindowDimensions from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
import StatusBar from '@libs/StatusBar';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
import CONST from '@src/CONST';
import BaseModal from './BaseModal';
import BaseModalProps from './types';
diff --git a/src/components/MoneyReportHeader.js b/src/components/MoneyReportHeader.js
index 9a1f59d64efa..f73ddef0dfa0 100644
--- a/src/components/MoneyReportHeader.js
+++ b/src/components/MoneyReportHeader.js
@@ -5,6 +5,7 @@ import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -12,7 +13,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import nextStepPropTypes from '@pages/nextStepPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/MoneyReportHeaderStatusBar.js b/src/components/MoneyReportHeaderStatusBar.js
index e693ce5e502b..687bc92ffbcd 100644
--- a/src/components/MoneyReportHeaderStatusBar.js
+++ b/src/components/MoneyReportHeaderStatusBar.js
@@ -1,9 +1,9 @@
import React, {useMemo} from 'react';
import {Text, View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as NextStepUtils from '@libs/NextStepUtils';
import nextStepPropTypes from '@pages/nextStepPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import RenderHTML from './RenderHTML';
diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js
index 1bd7b71c5aa3..65bffa9bffd6 100755
--- a/src/components/MoneyRequestConfirmationList.js
+++ b/src/components/MoneyRequestConfirmationList.js
@@ -9,6 +9,8 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
@@ -22,8 +24,6 @@ import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/MoneyRequestHeader.js b/src/components/MoneyRequestHeader.js
index 178163f6569f..488630dd0590 100644
--- a/src/components/MoneyRequestHeader.js
+++ b/src/components/MoneyRequestHeader.js
@@ -4,6 +4,7 @@ import React, {useCallback, useEffect, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import * as HeaderUtils from '@libs/HeaderUtils';
@@ -13,7 +14,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import iouReportPropTypes from '@pages/iouReportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/MoneyRequestHeaderStatusBar.js b/src/components/MoneyRequestHeaderStatusBar.js
index e50b69cca1fe..530524af12b0 100644
--- a/src/components/MoneyRequestHeaderStatusBar.js
+++ b/src/components/MoneyRequestHeaderStatusBar.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Text from './Text';
const propTypes = {
diff --git a/src/components/MoneyRequestSkeletonView.tsx b/src/components/MoneyRequestSkeletonView.tsx
index 3e175f000acd..e11e7bcecc07 100644
--- a/src/components/MoneyRequestSkeletonView.tsx
+++ b/src/components/MoneyRequestSkeletonView.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {Rect} from 'react-native-svg';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import SkeletonViewContentLoader from './SkeletonViewContentLoader';
diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
index a85322978b33..5c7ea712e772 100755
--- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
+++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js
@@ -7,6 +7,8 @@ import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
@@ -19,8 +21,6 @@ import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx
index a7b22a663e08..997e63cb022f 100644
--- a/src/components/MultipleAvatars.tsx
+++ b/src/components/MultipleAvatars.tsx
@@ -1,10 +1,10 @@
import React, {memo, useMemo} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import {ValueOf} from 'type-fest';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import {AvatarSource} from '@libs/UserUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {Icon} from '@src/types/onyx/OnyxCommon';
diff --git a/src/components/OfflineIndicator.tsx b/src/components/OfflineIndicator.tsx
index b402caa2c750..739befa7d081 100644
--- a/src/components/OfflineIndicator.tsx
+++ b/src/components/OfflineIndicator.tsx
@@ -2,8 +2,8 @@ import React, {useMemo} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx
index 78c93c250f84..5fcf1fe7442b 100644
--- a/src/components/OfflineWithFeedback.tsx
+++ b/src/components/OfflineWithFeedback.tsx
@@ -1,9 +1,9 @@
import React, {useCallback} from 'react';
import {ImageStyle, StyleProp, TextStyle, View, ViewStyle} from 'react-native';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import shouldRenderOffscreen from '@libs/shouldRenderOffscreen';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import ChildrenProps from '@src/types/utils/ChildrenProps';
diff --git a/src/components/Onfido/BaseOnfidoWeb.js b/src/components/Onfido/BaseOnfidoWeb.js
index 7a3b90945a5c..09ec96cf5b1e 100644
--- a/src/components/Onfido/BaseOnfidoWeb.js
+++ b/src/components/Onfido/BaseOnfidoWeb.js
@@ -3,10 +3,10 @@ import * as OnfidoSDK from 'onfido-sdk-ui';
import React, {forwardRef, useEffect} from 'react';
import _ from 'underscore';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
import Log from '@libs/Log';
-import fontFamily from '@styles/fontFamily';
-import fontWeightBold from '@styles/fontWeight/bold';
-import useTheme from '@styles/themes/useTheme';
+import fontFamily from '@styles/utils/fontFamily';
+import fontWeightBold from '@styles/utils/fontWeight/bold';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import './index.css';
diff --git a/src/components/Onfido/index.native.js b/src/components/Onfido/index.native.js
index ed0578187d3c..b0a0b3f4a466 100644
--- a/src/components/Onfido/index.native.js
+++ b/src/components/Onfido/index.native.js
@@ -2,9 +2,11 @@ import {OnfidoCaptureType, OnfidoCountryCode, OnfidoDocumentType, Onfido as Onfi
import lodashGet from 'lodash/get';
import React, {useEffect} from 'react';
import {Alert, Linking} from 'react-native';
+import {checkMultiple, PERMISSIONS, RESULTS} from 'react-native-permissions';
import _ from 'underscore';
import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import useLocalize from '@hooks/useLocalize';
+import getPlatform from '@libs/getPlatform';
import Log from '@libs/Log';
import CONST from '@src/CONST';
import onfidoPropTypes from './onfidoPropTypes';
@@ -39,30 +41,50 @@ function Onfido({sdkToken, onUserExit, onSuccess, onError}) {
return;
}
- // Handle user camera permission on iOS and Android
- if (_.contains([CONST.ONFIDO.ERROR.USER_CAMERA_PERMISSION, CONST.ONFIDO.ERROR.USER_CAMERA_DENINED, CONST.ONFIDO.ERROR.USER_CAMERA_CONSENT_DENIED], errorMessage)) {
- Alert.alert(
- translate('onfidoStep.cameraPermissionsNotGranted'),
- translate('onfidoStep.cameraRequestMessage'),
- [
- {
- text: translate('common.cancel'),
- onPress: () => onUserExit(),
- },
- {
- text: translate('common.settings'),
- onPress: () => {
- onUserExit();
- Linking.openSettings();
- },
- },
- ],
- {cancelable: false},
- );
- return;
- }
+ if (!_.isEmpty(errorMessage) && getPlatform() === CONST.PLATFORM.IOS) {
+ checkMultiple([PERMISSIONS.IOS.MICROPHONE, PERMISSIONS.IOS.CAMERA])
+ .then((statuses) => {
+ const isMicAllowed = statuses[PERMISSIONS.IOS.MICROPHONE] === RESULTS.GRANTED;
+ const isCameraAllowed = statuses[PERMISSIONS.IOS.CAMERA] === RESULTS.GRANTED;
+ let alertTitle = '';
+ let alertMessage = '';
+ if (!isCameraAllowed) {
+ alertTitle = 'onfidoStep.cameraPermissionsNotGranted';
+ alertMessage = 'onfidoStep.cameraRequestMessage';
+ } else if (!isMicAllowed) {
+ alertTitle = 'onfidoStep.microphonePermissionsNotGranted';
+ alertMessage = 'onfidoStep.microphoneRequestMessage';
+ }
- onError(errorMessage);
+ if (!_.isEmpty(alertTitle) && !_.isEmpty(alertMessage)) {
+ Alert.alert(
+ translate(alertTitle),
+ translate(alertMessage),
+ [
+ {
+ text: translate('common.cancel'),
+ onPress: () => onUserExit(),
+ },
+ {
+ text: translate('common.settings'),
+ onPress: () => {
+ onUserExit();
+ Linking.openSettings();
+ },
+ },
+ ],
+ {cancelable: false},
+ );
+ return;
+ }
+ onError(errorMessage);
+ })
+ .catch(() => {
+ onError(errorMessage);
+ });
+ } else {
+ onError(errorMessage);
+ }
});
// Onfido should be initialized only once on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js
index eaf3ccc7ead2..1a8c395ddd8b 100644
--- a/src/components/OptionRow.js
+++ b/src/components/OptionRow.js
@@ -3,11 +3,11 @@ import PropTypes from 'prop-types';
import React, {useEffect, useRef, useState} from 'react';
import {InteractionManager, StyleSheet, View} from 'react-native';
import _ from 'underscore';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import Button from './Button';
import DisplayNames from './DisplayNames';
@@ -194,7 +194,7 @@ function OptionRow(props) {
!props.onSelectRow && !props.isDisabled ? styles.cursorDefault : null,
]}
accessibilityLabel={props.option.text}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
hoverDimmingValue={1}
hoverStyle={!props.optionIsFocused ? props.hoverStyle || styles.sidebarLinkHover : undefined}
needsOffscreenAlphaCompositing={lodashGet(props.option, 'icons.length', 0) >= 2}
@@ -270,7 +270,7 @@ function OptionRow(props) {
props.onSelectedStatePressed(props.option)}
disabled={isDisabled}
- role={CONST.ACCESSIBILITY_ROLE.CHECKBOX}
+ role={CONST.ROLE.CHECKBOX}
accessibilityLabel={CONST.ACCESSIBILITY_ROLE.CHECKBOX}
>
diff --git a/src/components/OptionsList/BaseOptionsList.js b/src/components/OptionsList/BaseOptionsList.js
index 31bc4d4070af..d22df00bd0b3 100644
--- a/src/components/OptionsList/BaseOptionsList.js
+++ b/src/components/OptionsList/BaseOptionsList.js
@@ -7,7 +7,7 @@ import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
import SectionList from '@components/SectionList';
import Text from '@components/Text';
import usePrevious from '@hooks/usePrevious';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import {defaultProps as optionsListDefaultProps, propTypes as optionsListPropTypes} from './optionsListPropTypes';
diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js
index a151dca1f211..30e069d60aab 100755
--- a/src/components/OptionsSelector/BaseOptionsSelector.js
+++ b/src/components/OptionsSelector/BaseOptionsSelector.js
@@ -471,7 +471,7 @@ class BaseOptionsSelector extends Component {
value={this.props.value}
label={this.props.textInputLabel}
accessibilityLabel={this.props.textInputLabel}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
onChangeText={this.updateSearchValue}
errorText={this.state.errorMessage}
onSubmitEditing={this.selectFocusedOption}
diff --git a/src/components/PDFView/PDFInfoMessage.js b/src/components/PDFView/PDFInfoMessage.js
index 9ec53b2ae375..7c234b19daa5 100644
--- a/src/components/PDFView/PDFInfoMessage.js
+++ b/src/components/PDFView/PDFInfoMessage.js
@@ -6,7 +6,7 @@ import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/components/PDFView/PDFPasswordForm.js b/src/components/PDFView/PDFPasswordForm.js
index e20e2c44a76e..42d2ebbb771e 100644
--- a/src/components/PDFView/PDFPasswordForm.js
+++ b/src/components/PDFView/PDFPasswordForm.js
@@ -6,10 +6,10 @@ import Button from '@components/Button';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import shouldDelayFocus from '@libs/shouldDelayFocus';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import PDFInfoMessage from './PDFInfoMessage';
@@ -123,7 +123,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat
ref={textInputRef}
label={translate('common.password')}
accessibilityLabel={translate('common.password')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
/**
* This is a workaround to bypass Safari's autofill odd behaviour.
* This tricks the browser not to fill the username somewhere else and still fill the password correctly.
diff --git a/src/components/PDFView/index.js b/src/components/PDFView/index.js
index 50e737ba54d3..e18c52b06972 100644
--- a/src/components/PDFView/index.js
+++ b/src/components/PDFView/index.js
@@ -329,7 +329,7 @@ class PDFView extends Component {
{this.renderPDFView()}
diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js
index 30d5e4c48d68..bfdb80131aa6 100644
--- a/src/components/PDFView/index.native.js
+++ b/src/components/PDFView/index.native.js
@@ -186,7 +186,7 @@ class PDFView extends Component {
{this.renderPDFView()}
diff --git a/src/components/ParentNavigationSubtitle.tsx b/src/components/ParentNavigationSubtitle.tsx
index e65a8617a996..b3f1653fda1a 100644
--- a/src/components/ParentNavigationSubtitle.tsx
+++ b/src/components/ParentNavigationSubtitle.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {StyleProp, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {ParentNavigationSummaryParams} from '@src/languages/types';
import ROUTES from '@src/ROUTES';
@@ -31,7 +31,7 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID));
}}
accessibilityLabel={translate('threads.parentNavigationSummary', {rootReportName, workspaceName})}
- role={CONST.ACCESSIBILITY_ROLE.LINK}
+ role={CONST.ROLE.LINK}
style={pressableStyles}
>
ReactElement;
diff --git a/src/components/PinButton.js b/src/components/PinButton.js
index 84e7e4d4807e..182e49054100 100644
--- a/src/components/PinButton.js
+++ b/src/components/PinButton.js
@@ -1,7 +1,7 @@
import React from 'react';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
@@ -31,7 +31,7 @@ function PinButton(props) {
style={[styles.touchableButtonImage]}
ariaChecked={props.report.isPinned}
accessibilityLabel={props.report.isPinned ? props.translate('common.unPin') : props.translate('common.pin')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{isChecked && (
diff --git a/src/components/RadioButtonWithLabel.tsx b/src/components/RadioButtonWithLabel.tsx
index 7d8df23bae49..4c223262ac50 100644
--- a/src/components/RadioButtonWithLabel.tsx
+++ b/src/components/RadioButtonWithLabel.tsx
@@ -1,6 +1,6 @@
import React, {ComponentType} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import FormHelpMessage from './FormHelpMessage';
import * as Pressables from './Pressable';
import RadioButton from './RadioButton';
diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx
index b83710bd85bf..8aa3ef7e8ffe 100644
--- a/src/components/RadioButtons.tsx
+++ b/src/components/RadioButtons.tsx
@@ -1,5 +1,5 @@
import React, {useState} from 'react';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import RadioButtonWithLabel from './RadioButtonWithLabel';
type Choice = {
diff --git a/src/components/Reactions/AddReactionBubble.js b/src/components/Reactions/AddReactionBubble.js
index 994d467dfd6e..61ad4ce76d64 100644
--- a/src/components/Reactions/AddReactionBubble.js
+++ b/src/components/Reactions/AddReactionBubble.js
@@ -7,9 +7,9 @@ import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip/PopoverAnchorTooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import getButtonState from '@libs/getButtonState';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
import * as Session from '@userActions/Session';
@@ -100,7 +100,7 @@ function AddReactionBubble(props) {
e.preventDefault();
}}
accessibilityLabel={props.translate('emojiReactions.addReactionTooltip')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
// disable dimming
pressDimmingValue={1}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
diff --git a/src/components/Reactions/EmojiReactionBubble.js b/src/components/Reactions/EmojiReactionBubble.js
index 7fcdae8c0a5a..3fd22a758f67 100644
--- a/src/components/Reactions/EmojiReactionBubble.js
+++ b/src/components/Reactions/EmojiReactionBubble.js
@@ -4,8 +4,8 @@ import PressableWithSecondaryInteraction from '@components/PressableWithSecondar
import Text from '@components/Text';
import {withCurrentUserPersonalDetailsDefaultProps} from '@components/withCurrentUserPersonalDetails';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -83,7 +83,7 @@ function EmojiReactionBubble(props) {
// Prevent text input blur when emoji reaction is left clicked
e.preventDefault();
}}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.emojiCodes.join('')}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
>
diff --git a/src/components/Reactions/MiniQuickEmojiReactions.js b/src/components/Reactions/MiniQuickEmojiReactions.js
index 92913a7c4c5e..34d336887031 100644
--- a/src/components/Reactions/MiniQuickEmojiReactions.js
+++ b/src/components/Reactions/MiniQuickEmojiReactions.js
@@ -8,11 +8,11 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as EmojiUtils from '@libs/EmojiUtils';
import getButtonState from '@libs/getButtonState';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
index 9d32b0240a23..c932632f7bff 100644
--- a/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
+++ b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
@@ -7,8 +7,8 @@ import AddReactionBubble from '@components/Reactions/AddReactionBubble';
import EmojiReactionBubble from '@components/Reactions/EmojiReactionBubble';
import EmojiReactionsPropTypes from '@components/Reactions/EmojiReactionsPropTypes';
import Tooltip from '@components/Tooltip';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as EmojiUtils from '@libs/EmojiUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/Reactions/ReactionTooltipContent.js b/src/components/Reactions/ReactionTooltipContent.js
index 1a7a06e9487d..bb6b03c5918b 100644
--- a/src/components/Reactions/ReactionTooltipContent.js
+++ b/src/components/Reactions/ReactionTooltipContent.js
@@ -5,8 +5,8 @@ import _ from 'underscore';
import Text from '@components/Text';
import {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/**
diff --git a/src/components/Reactions/ReportActionItemEmojiReactions.js b/src/components/Reactions/ReportActionItemEmojiReactions.js
index 7c504e35cb9f..547f4089857f 100644
--- a/src/components/Reactions/ReportActionItemEmojiReactions.js
+++ b/src/components/Reactions/ReportActionItemEmojiReactions.js
@@ -7,11 +7,11 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import Tooltip from '@components/Tooltip';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as EmojiUtils from '@libs/EmojiUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import {ReactionListContext} from '@pages/home/ReportScreenContext';
-import useThemeStyles from '@styles/useThemeStyles';
import AddReactionBubble from './AddReactionBubble';
import EmojiReactionBubble from './EmojiReactionBubble';
import EmojiReactionsPropTypes from './EmojiReactionsPropTypes';
diff --git a/src/components/ReceiptEmptyState.js b/src/components/ReceiptEmptyState.js
index 6af1cadd48c5..371518dd9a77 100644
--- a/src/components/ReceiptEmptyState.js
+++ b/src/components/ReceiptEmptyState.js
@@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/ReimbursementAccountLoadingIndicator.js b/src/components/ReimbursementAccountLoadingIndicator.js
index 72bf3ce1896d..bc0e70e64419 100644
--- a/src/components/ReimbursementAccountLoadingIndicator.js
+++ b/src/components/ReimbursementAccountLoadingIndicator.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {StyleSheet, View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import FullPageOfflineBlockingView from './BlockingViews/FullPageOfflineBlockingView';
import FullScreenLoadingIndicator from './FullscreenLoadingIndicator';
import HeaderWithBackButton from './HeaderWithBackButton';
diff --git a/src/components/ReportActionItem/ChronosOOOListActions.js b/src/components/ReportActionItem/ChronosOOOListActions.js
index 7c918b6a2d9c..f90ae67796b9 100644
--- a/src/components/ReportActionItem/ChronosOOOListActions.js
+++ b/src/components/ReportActionItem/ChronosOOOListActions.js
@@ -7,9 +7,9 @@ import Button from '@components/Button';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Chronos from '@userActions/Chronos';
const propTypes = {
diff --git a/src/components/ReportActionItem/MoneyReportView.js b/src/components/ReportActionItem/MoneyReportView.js
index c52d4abe371c..c12659e94673 100644
--- a/src/components/ReportActionItem/MoneyReportView.js
+++ b/src/components/ReportActionItem/MoneyReportView.js
@@ -7,13 +7,13 @@ import SpacerView from '@components/SpacerView';
import Text from '@components/Text';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/components/ReportActionItem/MoneyRequestAction.js b/src/components/ReportActionItem/MoneyRequestAction.js
index 040682990d2c..e0a3152a41b4 100644
--- a/src/components/ReportActionItem/MoneyRequestAction.js
+++ b/src/components/ReportActionItem/MoneyRequestAction.js
@@ -8,6 +8,7 @@ import {withNetwork} from '@components/OnyxProvider';
import refPropTypes from '@components/refPropTypes';
import RenderHTML from '@components/RenderHTML';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -17,7 +18,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js
index 210a0575a310..12c6d0629370 100644
--- a/src/components/ReportActionItem/MoneyRequestPreview.js
+++ b/src/components/ReportActionItem/MoneyRequestPreview.js
@@ -14,9 +14,11 @@ import refPropTypes from '@components/refPropTypes';
import {showContextMenuForReport} from '@components/ShowContextMenuContext';
import Text from '@components/Text';
import transactionPropTypes from '@components/transactionPropTypes';
-import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import compose from '@libs/compose';
import ControlSelection from '@libs/ControlSelection';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
@@ -28,9 +30,8 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import walletTermsPropTypes from '@pages/EnablePayments/walletTermsPropTypes';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import iouReportPropTypes from '@pages/iouReportPropTypes';
+import reportPropTypes from '@pages/reportPropTypes';
import * as PaymentMethods from '@userActions/PaymentMethods';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
@@ -64,20 +65,11 @@ const propTypes = {
/* Onyx Props */
- /** Active IOU Report for current report */
- iouReport: PropTypes.shape({
- /** Account ID of the manager in this iou report */
- managerID: PropTypes.number,
+ /** chatReport associated with iouReport */
+ chatReport: reportPropTypes,
- /** Account ID of the creator of this iou report */
- ownerAccountID: PropTypes.number,
-
- /** Outstanding amount in cents of this transaction */
- total: PropTypes.number,
-
- /** Currency of outstanding amount of this transaction */
- currency: PropTypes.string,
- }),
+ /** IOU report data object */
+ iouReport: iouReportPropTypes,
/** True if this is this IOU is a split instead of a 1:1 request */
isBillSplit: PropTypes.bool.isRequired,
@@ -112,8 +104,6 @@ const propTypes = {
/** Whether a message is a whisper */
isWhisper: PropTypes.bool,
-
- ...withLocalizePropTypes,
};
const defaultProps = {
@@ -124,6 +114,7 @@ const defaultProps = {
checkIfContextMenuActive: () => {},
containerStyles: [],
walletTerms: {},
+ chatReport: {},
isHovered: false,
personalDetails: {},
session: {
@@ -138,6 +129,7 @@ function MoneyRequestPreview(props) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
+ const {translate} = useLocalize();
const {isSmallScreenWidth, windowWidth} = useWindowDimensions();
if (_.isEmpty(props.iouReport) && !props.isBillSplit) {
@@ -179,14 +171,9 @@ function MoneyRequestPreview(props) {
const getSettledMessage = () => {
if (isExpensifyCardTransaction) {
- return props.translate('common.done');
- }
- switch (lodashGet(props.action, 'originalMessage.paymentType', '')) {
- case CONST.IOU.PAYMENT_TYPE.EXPENSIFY:
- return props.translate('iou.settledExpensify');
- default:
- return props.translate('iou.settledElsewhere');
+ return translate('common.done');
}
+ return translate('iou.settledExpensify');
};
const showContextMenu = (event) => {
@@ -195,43 +182,43 @@ function MoneyRequestPreview(props) {
const getPreviewHeaderText = () => {
if (isDistanceRequest) {
- return props.translate('common.distance');
+ return translate('common.distance');
}
if (isScanning) {
- return props.translate('common.receipt');
+ return translate('common.receipt');
}
if (props.isBillSplit) {
- return props.translate('iou.split');
+ return translate('iou.split');
}
if (isExpensifyCardTransaction) {
- let message = props.translate('iou.card');
+ let message = translate('iou.card');
if (TransactionUtils.isPending(props.transaction)) {
- message += ` • ${props.translate('iou.pending')}`;
+ message += ` • ${translate('iou.pending')}`;
}
return message;
}
- let message = props.translate('iou.cash');
+ let message = translate('iou.cash');
if (ReportUtils.isGroupPolicyExpenseReport(props.iouReport) && ReportUtils.isReportApproved(props.iouReport) && !ReportUtils.isSettled(props.iouReport)) {
- message += ` • ${props.translate('iou.approved')}`;
+ message += ` • ${translate('iou.approved')}`;
} else if (props.iouReport.isWaitingOnBankAccount) {
- message += ` • ${props.translate('iou.pending')}`;
+ message += ` • ${translate('iou.pending')}`;
} else if (props.iouReport.isCancelledIOU) {
- message += ` • ${props.translate('iou.canceled')}`;
+ message += ` • ${translate('iou.canceled')}`;
}
return message;
};
const getDisplayAmountText = () => {
if (isDistanceRequest) {
- return requestAmount && !hasPendingWaypoints ? CurrencyUtils.convertToDisplayString(requestAmount, props.transaction.currency) : props.translate('common.tbd');
+ return requestAmount && !hasPendingWaypoints ? CurrencyUtils.convertToDisplayString(requestAmount, props.transaction.currency) : translate('common.tbd');
}
if (isScanning) {
- return props.translate('iou.receiptScanning');
+ return translate('iou.receiptScanning');
}
if (TransactionUtils.hasMissingSmartscanFields(props.transaction)) {
@@ -331,14 +318,14 @@ function MoneyRequestPreview(props) {
{shouldShowMerchant && !props.isBillSplit && (
- {hasPendingWaypoints ? requestMerchant.replace(CONST.REGEX.FIRST_SPACE, props.translate('common.tbd')) : requestMerchant}
+ {hasPendingWaypoints ? requestMerchant.replace(CONST.REGEX.FIRST_SPACE, translate('common.tbd')) : requestMerchant}
)}
{!isCurrentUserManager && props.shouldShowPendingConversionMessage && (
- {props.translate('iou.pendingConversionMessage')}
+ {translate('iou.pendingConversionMessage')}
)}
{(shouldShowDescription || (shouldShowMerchant && props.isBillSplit)) && (
{shouldShowDescription ? description : requestMerchant}
@@ -346,7 +333,7 @@ function MoneyRequestPreview(props) {
{props.isBillSplit && !_.isEmpty(participantAccountIDs) && requestAmount > 0 && (
- {props.translate('iou.amountEach', {
+ {translate('iou.amountEach', {
amount: CurrencyUtils.convertToDisplayString(
IOUUtils.calculateAmount(isPolicyExpenseChat ? 1 : participantAccountIDs.length - 1, requestAmount, requestCurrency),
requestCurrency,
@@ -374,7 +361,7 @@ function MoneyRequestPreview(props) {
onPressIn={() => DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()}
onPressOut={() => ControlSelection.unblock()}
onLongPress={showContextMenu}
- accessibilityLabel={props.isBillSplit ? props.translate('iou.split') : props.translate('iou.cash')}
+ accessibilityLabel={props.isBillSplit ? translate('iou.split') : translate('iou.cash')}
accessibilityHint={CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency)}
style={[styles.moneyRequestPreviewBox, ...props.containerStyles, shouldDisableOnPress && styles.cursorDefault]}
>
@@ -387,26 +374,23 @@ MoneyRequestPreview.propTypes = propTypes;
MoneyRequestPreview.defaultProps = defaultProps;
MoneyRequestPreview.displayName = 'MoneyRequestPreview';
-export default compose(
- withLocalize,
- withOnyx({
- personalDetails: {
- key: ONYXKEYS.PERSONAL_DETAILS_LIST,
- },
- chatReport: {
- key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
- },
- iouReport: {
- key: ({iouReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`,
- },
- session: {
- key: ONYXKEYS.SESSION,
- },
- transaction: {
- key: ({action}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${(action && action.originalMessage && action.originalMessage.IOUTransactionID) || 0}`,
- },
- walletTerms: {
- key: ONYXKEYS.WALLET_TERMS,
- },
- }),
-)(MoneyRequestPreview);
+export default withOnyx({
+ personalDetails: {
+ key: ONYXKEYS.PERSONAL_DETAILS_LIST,
+ },
+ chatReport: {
+ key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`,
+ },
+ iouReport: {
+ key: ({iouReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`,
+ },
+ session: {
+ key: ONYXKEYS.SESSION,
+ },
+ transaction: {
+ key: ({action}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${(action && action.originalMessage && action.originalMessage.IOUTransactionID) || 0}`,
+ },
+ walletTerms: {
+ key: ONYXKEYS.WALLET_TERMS,
+ },
+})(MoneyRequestPreview);
diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js
index 1afc909b54df..817c88d456db 100644
--- a/src/components/ReportActionItem/MoneyRequestView.js
+++ b/src/components/ReportActionItem/MoneyRequestView.js
@@ -17,6 +17,9 @@ import transactionPropTypes from '@components/transactionPropTypes';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as CardUtils from '@libs/CardUtils';
import compose from '@libs/compose';
@@ -32,9 +35,6 @@ import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateB
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import iouReportPropTypes from '@pages/iouReportPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/ReportActionItem/RenameAction.js b/src/components/ReportActionItem/RenameAction.js
index b4f4b23c9ebf..52039b7b593b 100644
--- a/src/components/ReportActionItem/RenameAction.js
+++ b/src/components/ReportActionItem/RenameAction.js
@@ -4,9 +4,9 @@ import React from 'react';
import Text from '@components/Text';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** All the data of the action */
diff --git a/src/components/ReportActionItem/ReportActionItemImage.js b/src/components/ReportActionItem/ReportActionItemImage.js
index 6fd322a24d3c..2c5ef22b1b8e 100644
--- a/src/components/ReportActionItem/ReportActionItemImage.js
+++ b/src/components/ReportActionItem/ReportActionItemImage.js
@@ -10,9 +10,9 @@ import {ShowContextMenuContext} from '@components/ShowContextMenuContext';
import ThumbnailImage from '@components/ThumbnailImage';
import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TransactionUtils from '@libs/TransactionUtils';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -94,7 +94,7 @@ function ReportActionItemImage({thumbnail, image, enablePreviewModal, transactio
{receiptImageComponent}
diff --git a/src/components/ReportActionItem/ReportActionItemImages.js b/src/components/ReportActionItem/ReportActionItemImages.js
index b20513d63fe3..96f919aea750 100644
--- a/src/components/ReportActionItem/ReportActionItemImages.js
+++ b/src/components/ReportActionItem/ReportActionItemImages.js
@@ -5,9 +5,9 @@ import {Polygon, Svg} from 'react-native-svg';
import _ from 'underscore';
import Text from '@components/Text';
import transactionPropTypes from '@components/transactionPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import ReportActionItemImage from './ReportActionItemImage';
diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js
index e6b387f362ef..aa3c02b76fc0 100644
--- a/src/components/ReportActionItem/ReportPreview.js
+++ b/src/components/ReportActionItem/ReportPreview.js
@@ -14,6 +14,8 @@ import {showContextMenuForReport} from '@components/ShowContextMenuContext';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import ControlSelection from '@libs/ControlSelection';
import * as CurrencyUtils from '@libs/CurrencyUtils';
@@ -25,8 +27,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/ReportActionItem/TaskAction.js b/src/components/ReportActionItem/TaskAction.js
index d79bb6f78b93..5825d623a5ca 100644
--- a/src/components/ReportActionItem/TaskAction.js
+++ b/src/components/ReportActionItem/TaskAction.js
@@ -3,8 +3,8 @@ import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TaskUtils from '@libs/TaskUtils';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** Name of the reportAction action */
diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js
index c22181fec775..ed875bb04af2 100644
--- a/src/components/ReportActionItem/TaskPreview.js
+++ b/src/components/ReportActionItem/TaskPreview.js
@@ -14,6 +14,8 @@ import RenderHTML from '@components/RenderHTML';
import {showContextMenuForReport} from '@components/ShowContextMenuContext';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import ControlSelection from '@libs/ControlSelection';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
@@ -23,8 +25,6 @@ import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import * as TaskUtils from '@libs/TaskUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
@@ -108,7 +108,7 @@ function TaskPreview(props) {
onPressOut={() => ControlSelection.unblock()}
onLongPress={(event) => showContextMenuForReport(event, props.contextMenuAnchor, props.chatReportID, props.action, props.checkIfContextMenuActive)}
style={[styles.flexRow, styles.justifyContentBetween]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('task.task')}
>
diff --git a/src/components/ReportActionItem/TaskView.js b/src/components/ReportActionItem/TaskView.js
index ea02dba705a6..bb8945495018 100644
--- a/src/components/ReportActionItem/TaskView.js
+++ b/src/components/ReportActionItem/TaskView.js
@@ -17,6 +17,8 @@ import Text from '@components/Text';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import convertToLTR from '@libs/convertToLTR';
import getButtonState from '@libs/getButtonState';
@@ -24,8 +26,6 @@ import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
diff --git a/src/components/ReportActionsSkeletonView/SkeletonViewLines.tsx b/src/components/ReportActionsSkeletonView/SkeletonViewLines.tsx
index 3451e13298b3..c4c2a3f43eb3 100644
--- a/src/components/ReportActionsSkeletonView/SkeletonViewLines.tsx
+++ b/src/components/ReportActionsSkeletonView/SkeletonViewLines.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {Circle, Rect} from 'react-native-svg';
import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
type SkeletonViewLinesProps = {
diff --git a/src/components/ReportHeaderSkeletonView.tsx b/src/components/ReportHeaderSkeletonView.tsx
index 8f13fcbf7a1b..91adb26faff5 100644
--- a/src/components/ReportHeaderSkeletonView.tsx
+++ b/src/components/ReportHeaderSkeletonView.tsx
@@ -2,9 +2,9 @@ import React from 'react';
import {View} from 'react-native';
import {Circle, Rect} from 'react-native-svg';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import Icon from './Icon';
@@ -30,7 +30,7 @@ function ReportHeaderSkeletonView({shouldAnimate = true, onBackButtonPress = ()
diff --git a/src/components/ReportWelcomeText.js b/src/components/ReportWelcomeText.js
index 6613517b2ed2..a204d0c59aaf 100644
--- a/src/components/ReportWelcomeText.js
+++ b/src/components/ReportWelcomeText.js
@@ -4,13 +4,13 @@ import React from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js
index ff6a3c4562b3..5a6363d4a642 100644
--- a/src/components/RoomHeaderAvatars.js
+++ b/src/components/RoomHeaderAvatars.js
@@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
import React, {memo} from 'react';
import {View} from 'react-native';
import _ from 'underscore';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as UserUtils from '@libs/UserUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import AttachmentModal from './AttachmentModal';
import Avatar from './Avatar';
@@ -42,7 +42,7 @@ function RoomHeaderAvatars(props) {
@@ -30,7 +31,7 @@ function SAMLLoadingIndicator() {
diff --git a/src/components/SafeArea/index.ios.tsx b/src/components/SafeArea/index.ios.tsx
index 194919b3eef4..1b2e1881ade3 100644
--- a/src/components/SafeArea/index.ios.tsx
+++ b/src/components/SafeArea/index.ios.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import {SafeAreaView} from 'react-native-safe-area-context';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import SafeAreaProps from './types';
function SafeArea({children}: SafeAreaProps) {
diff --git a/src/components/SafeAreaConsumer/index.android.tsx b/src/components/SafeAreaConsumer/index.android.tsx
index 5117000627cf..4e6c9bbd3528 100644
--- a/src/components/SafeAreaConsumer/index.android.tsx
+++ b/src/components/SafeAreaConsumer/index.android.tsx
@@ -1,8 +1,8 @@
import React from 'react';
// eslint-disable-next-line no-restricted-imports
import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
+import useStyleUtils from '@hooks/useStyleUtils';
import StatusBar from '@libs/StatusBar';
-import useStyleUtils from '@styles/useStyleUtils';
import SafeAreaConsumerProps from './types';
/**
diff --git a/src/components/SafeAreaConsumer/index.tsx b/src/components/SafeAreaConsumer/index.tsx
index 54c5d984be5f..c05e836a2348 100644
--- a/src/components/SafeAreaConsumer/index.tsx
+++ b/src/components/SafeAreaConsumer/index.tsx
@@ -1,7 +1,7 @@
import React from 'react';
// eslint-disable-next-line no-restricted-imports
import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
-import useStyleUtils from '@styles/useStyleUtils';
+import useStyleUtils from '@hooks/useStyleUtils';
import SafeAreaConsumerProps from './types';
/**
diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js
index 6af67c51ffaf..bd277ffa1ab8 100644
--- a/src/components/ScreenWrapper/index.js
+++ b/src/components/ScreenWrapper/index.js
@@ -14,9 +14,9 @@ import useEnvironment from '@hooks/useEnvironment';
import useInitialDimensions from '@hooks/useInitialWindowDimensions';
import useKeyboardState from '@hooks/useKeyboardState';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
-import useThemeStyles from '@styles/useThemeStyles';
import toggleTestToolsModal from '@userActions/TestTool';
import CONST from '@src/CONST';
import {defaultProps, propTypes} from './propTypes';
diff --git a/src/components/Section.js b/src/components/Section.js
index ad52bf0e3509..a59476fb0c05 100644
--- a/src/components/Section.js
+++ b/src/components/Section.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Icon from './Icon';
import MenuItemList from './MenuItemList';
import menuItemPropTypes from './menuItemPropTypes';
diff --git a/src/components/SelectCircle.tsx b/src/components/SelectCircle.tsx
index 7a7e23388722..637c06f4d35f 100644
--- a/src/components/SelectCircle.tsx
+++ b/src/components/SelectCircle.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
diff --git a/src/components/SelectionList/BaseListItem.js b/src/components/SelectionList/BaseListItem.js
index c2e468359f3f..ac679f32d103 100644
--- a/src/components/SelectionList/BaseListItem.js
+++ b/src/components/SelectionList/BaseListItem.js
@@ -7,9 +7,9 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import RadioListItem from './RadioListItem';
import {baseListItemPropTypes} from './selectionListPropTypes';
@@ -44,7 +44,7 @@ function BaseListItem({
onPress={() => onSelectRow(item)}
disabled={isDisabled}
accessibilityLabel={item.text}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
hoverDimmingValue={1}
hoverStyle={styles.hoveredComponentBG}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js
index 79e38b304cdb..454127612e0d 100644
--- a/src/components/SelectionList/BaseSelectionList.js
+++ b/src/components/SelectionList/BaseSelectionList.js
@@ -17,9 +17,10 @@ import withKeyboardState, {keyboardStatePropTypes} from '@components/withKeyboar
import useActiveElement from '@hooks/useActiveElement';
import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Log from '@libs/Log';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import BaseListItem from './BaseListItem';
@@ -55,6 +56,8 @@ function BaseSelectionList({
showConfirmButton = false,
shouldPreventDefaultFocusOnSelectRow = false,
isKeyboardShown = false,
+ containerStyle = [],
+ disableInitialFocusOptionStyle = false,
inputRef = null,
disableKeyboardShortcuts = false,
children,
@@ -63,6 +66,7 @@ function BaseSelectionList({
}) {
const theme = useTheme();
const styles = useThemeStyles();
+ const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const listRef = useRef(null);
const textInputRef = useRef(null);
@@ -152,7 +156,7 @@ function BaseSelectionList({
const [focusedIndex, setFocusedIndex] = useState(() => _.findIndex(flattenedSections.allOptions, (option) => option.keyForList === initiallyFocusedOptionKey));
// Disable `Enter` shortcut if the active element is a button or checkbox
- const disableEnterShortcut = activeElement && [CONST.ACCESSIBILITY_ROLE.BUTTON, CONST.ACCESSIBILITY_ROLE.CHECKBOX].includes(activeElement.role);
+ const disableEnterShortcut = activeElement && [CONST.ROLE.BUTTON, CONST.ROLE.CHECKBOX].includes(activeElement.role);
/**
* Scrolls to the desired item index in the section list
@@ -310,6 +314,7 @@ function BaseSelectionList({
showTooltip={showTooltip}
canSelectMultiple={canSelectMultiple}
onSelectRow={() => selectRow(item, true)}
+ disableIsFocusStyle={disableInitialFocusOptionStyle}
onDismissError={onDismissError}
shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow}
keyForList={item.keyForList}
@@ -393,9 +398,10 @@ function BaseSelectionList({
maxIndex={flattenedSections.allOptions.length - 1}
onFocusedIndexChanged={updateAndScrollToFocusedIndex}
>
+ {/* */}
{({safeAreaPaddingBottomStyle}) => (
-
+
{shouldShowTextInput && (
@@ -84,7 +84,7 @@ function GoogleSignIn({translate, isDesktopFlow}) {
diff --git a/src/components/SignInButtons/IconButton.js b/src/components/SignInButtons/IconButton.js
index 706ceb2edc3f..19a5bd9b27b8 100644
--- a/src/components/SignInButtons/IconButton.js
+++ b/src/components/SignInButtons/IconButton.js
@@ -4,7 +4,7 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -38,7 +38,7 @@ function IconButton({onPress, translate, provider}) {
onSelectOption(option)}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityState={{checked: selectedOptionKey === option.key}}
aria-checked={selectedOptionKey === option.key}
accessibilityLabel={option.label}
diff --git a/src/components/SpacerView.js b/src/components/SpacerView.js
index b9705a15b5f3..6b3ece2d476f 100644
--- a/src/components/SpacerView.js
+++ b/src/components/SpacerView.js
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import usePrevious from '@hooks/usePrevious';
+import useStyleUtils from '@hooks/useStyleUtils';
import stylePropTypes from '@styles/stylePropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/components/SplashScreenHider/index.native.tsx b/src/components/SplashScreenHider/index.native.tsx
index 29b5ae710dda..9585d0d5abeb 100644
--- a/src/components/SplashScreenHider/index.native.tsx
+++ b/src/components/SplashScreenHider/index.native.tsx
@@ -2,11 +2,11 @@ import {useCallback, useRef} from 'react';
import {StyleSheet, ViewStyle} from 'react-native';
import Reanimated, {Easing, runOnJS, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import Logo from '@assets/images/new-expensify-dark.svg';
+import useThemeStyles from '@hooks/useThemeStyles';
import BootSplash from '@libs/BootSplash';
-import useThemeStyles from '@styles/useThemeStyles';
-import type SplashScreenHiderProps from './types';
+import type {SplashScreenHiderProps, SplashScreenHiderReturnType} from './types';
-function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps) {
+function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps): SplashScreenHiderReturnType {
const styles = useThemeStyles();
const logoSizeRatio = BootSplash.logoSizeRatio || 1;
const navigationBarHeight = BootSplash.navigationBarHeight || 0;
diff --git a/src/components/SplashScreenHider/index.tsx b/src/components/SplashScreenHider/index.tsx
index d3f5c52c1e3e..5710055b80ed 100644
--- a/src/components/SplashScreenHider/index.tsx
+++ b/src/components/SplashScreenHider/index.tsx
@@ -1,8 +1,8 @@
import {useEffect} from 'react';
import BootSplash from '@libs/BootSplash';
-import type SplashScreenHiderProps from './types';
+import type {SplashScreenHiderProps, SplashScreenHiderReturnType} from './types';
-function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps) {
+function SplashScreenHider({onHide = () => {}}: SplashScreenHiderProps): SplashScreenHiderReturnType {
useEffect(() => {
BootSplash.hide().then(() => onHide());
}, [onHide]);
diff --git a/src/components/SplashScreenHider/types.ts b/src/components/SplashScreenHider/types.ts
index 4ea25da93290..ff7b2beb1520 100644
--- a/src/components/SplashScreenHider/types.ts
+++ b/src/components/SplashScreenHider/types.ts
@@ -1,6 +1,10 @@
+import {ReactNode} from 'react';
+
type SplashScreenHiderProps = {
/** Splash screen has been hidden */
onHide: () => void;
};
-export default SplashScreenHiderProps;
+type SplashScreenHiderReturnType = ReactNode;
+
+export type {SplashScreenHiderProps, SplashScreenHiderReturnType};
diff --git a/src/components/StatePicker/StateSelectorModal.js b/src/components/StatePicker/StateSelectorModal.js
index 908bb5eb5b2a..003211478529 100644
--- a/src/components/StatePicker/StateSelectorModal.js
+++ b/src/components/StatePicker/StateSelectorModal.js
@@ -7,9 +7,9 @@ import Modal from '@components/Modal';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import searchCountryOptions from '@libs/searchCountryOptions';
import StringUtils from '@libs/StringUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/components/StatePicker/index.js b/src/components/StatePicker/index.js
index d9c137ac9dc1..6fa60fbba947 100644
--- a/src/components/StatePicker/index.js
+++ b/src/components/StatePicker/index.js
@@ -7,7 +7,7 @@ import FormHelpMessage from '@components/FormHelpMessage';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import refPropTypes from '@components/refPropTypes';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import StateSelectorModal from './StateSelectorModal';
const propTypes = {
diff --git a/src/components/SubscriptAvatar.tsx b/src/components/SubscriptAvatar.tsx
index 7fa2900eaffb..9a0aa934ff1b 100644
--- a/src/components/SubscriptAvatar.tsx
+++ b/src/components/SubscriptAvatar.tsx
@@ -1,10 +1,10 @@
import React, {memo} from 'react';
import {View} from 'react-native';
import {ValueOf} from 'type-fest';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {AvatarSource} from '@libs/UserUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {AvatarType} from '@src/types/onyx/OnyxCommon';
import Avatar from './Avatar';
diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx
index 2398f531628d..fd9d9ae315ff 100644
--- a/src/components/Switch.tsx
+++ b/src/components/Switch.tsx
@@ -1,7 +1,7 @@
import React, {useEffect, useRef} from 'react';
import {Animated} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import useNativeDriver from '@libs/useNativeDriver';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
@@ -38,7 +38,7 @@ function Switch({isOn, onToggle, accessibilityLabel}: SwitchProps) {
style={[styles.switchTrack, !isOn && styles.switchInactive]}
onPress={() => onToggle(!isOn)}
onLongPress={() => onToggle(!isOn)}
- role={CONST.ACCESSIBILITY_ROLE.SWITCH}
+ role={CONST.ROLE.SWITCH}
aria-checked={isOn}
accessibilityLabel={accessibilityLabel}
// disable hover dim for switch
diff --git a/src/components/TabSelector/TabIcon.js b/src/components/TabSelector/TabIcon.js
index 76217b69e9f3..d96ae19897f4 100644
--- a/src/components/TabSelector/TabIcon.js
+++ b/src/components/TabSelector/TabIcon.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {Animated, StyleSheet, View} from 'react-native';
import Icon from '@components/Icon';
-import useTheme from '@styles/themes/useTheme';
+import useTheme from '@hooks/useTheme';
const propTypes = {
/** Icon to display on tab */
diff --git a/src/components/TabSelector/TabLabel.js b/src/components/TabSelector/TabLabel.js
index 5dc050731fc5..fdf204011152 100644
--- a/src/components/TabSelector/TabLabel.js
+++ b/src/components/TabSelector/TabLabel.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import {Animated, StyleSheet, Text, View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
const propTypes = {
/** Title of the tab */
diff --git a/src/components/TabSelector/TabSelector.js b/src/components/TabSelector/TabSelector.js
index e968226e83fa..444bb62263d9 100644
--- a/src/components/TabSelector/TabSelector.js
+++ b/src/components/TabSelector/TabSelector.js
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import _ from 'underscore';
import * as Expensicons from '@components/Icon/Expensicons';
import useLocalize from '@hooks/useLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import TabSelectorItem from './TabSelectorItem';
diff --git a/src/components/TabSelector/TabSelectorItem.js b/src/components/TabSelector/TabSelectorItem.js
index 116b5db02d2c..88aa98766fae 100644
--- a/src/components/TabSelector/TabSelectorItem.js
+++ b/src/components/TabSelector/TabSelectorItem.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {Animated, StyleSheet} from 'react-native';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import TabIcon from './TabIcon';
import TabLabel from './TabLabel';
diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js
index 334ca3e38370..cb3d9bf260e6 100644
--- a/src/components/TagPicker/index.js
+++ b/src/components/TagPicker/index.js
@@ -4,10 +4,10 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import OptionsSelector from '@components/OptionsSelector';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {defaultProps, propTypes} from './tagPickerPropTypes';
diff --git a/src/components/TaskHeaderActionButton.tsx b/src/components/TaskHeaderActionButton.tsx
index 5f8461d8e324..47975fd7fc1e 100644
--- a/src/components/TaskHeaderActionButton.tsx
+++ b/src/components/TaskHeaderActionButton.tsx
@@ -2,8 +2,8 @@ import React from 'react';
import {View} from 'react-native';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as Task from '@userActions/Task';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/TestToolMenu.tsx b/src/components/TestToolMenu.tsx
index 53953b861d7d..82b597f77268 100644
--- a/src/components/TestToolMenu.tsx
+++ b/src/components/TestToolMenu.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ApiUtils from '@libs/ApiUtils';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Network from '@userActions/Network';
import * as Session from '@userActions/Session';
import * as User from '@userActions/User';
diff --git a/src/components/TestToolRow.tsx b/src/components/TestToolRow.tsx
index 4999866b27ee..4ed1aa126002 100644
--- a/src/components/TestToolRow.tsx
+++ b/src/components/TestToolRow.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Text from './Text';
type TestToolRowProps = {
diff --git a/src/components/TestToolsModal.tsx b/src/components/TestToolsModal.tsx
index f555c2b0b4fe..4138df64adc2 100644
--- a/src/components/TestToolsModal.tsx
+++ b/src/components/TestToolsModal.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import {OnyxEntry, withOnyx} from 'react-native-onyx';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import toggleTestToolsModal from '@userActions/TestTool';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/Text.tsx b/src/components/Text.tsx
index ae2f6ba99392..0d201bd253c4 100644
--- a/src/components/Text.tsx
+++ b/src/components/Text.tsx
@@ -1,8 +1,8 @@
import React, {ForwardedRef} from 'react';
import {Text as RNText, TextProps as RNTextProps, StyleSheet} from 'react-native';
import type {TextStyle} from 'react-native';
-import fontFamily from '@styles/fontFamily';
-import useTheme from '@styles/themes/useTheme';
+import useTheme from '@hooks/useTheme';
+import fontFamily from '@styles/utils/fontFamily';
import variables from '@styles/variables';
import ChildrenProps from '@src/types/utils/ChildrenProps';
diff --git a/src/components/TextInput/BaseTextInput/index.js b/src/components/TextInput/BaseTextInput/index.js
index 9c9afb6ebacc..67776d6c7e91 100644
--- a/src/components/TextInput/BaseTextInput/index.js
+++ b/src/components/TextInput/BaseTextInput/index.js
@@ -13,12 +13,12 @@ import Text from '@components/Text';
import * as styleConst from '@components/TextInput/styleConst';
import TextInputLabel from '@components/TextInput/TextInputLabel';
import withLocalize from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import isInputAutoFilled from '@libs/isInputAutoFilled';
import useNativeDriver from '@libs/useNativeDriver';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import * as baseTextInputPropTypes from './baseTextInputPropTypes';
@@ -262,6 +262,7 @@ function BaseTextInput(props) {
style={[
props.autoGrowHeight && styles.autoGrowHeightInputContainer(textInputHeight, variables.componentSizeLarge, maxHeight),
!isMultiline && styles.componentHeightLarge,
+ ...props.containerStyles,
]}
>
{label}
diff --git a/src/components/TextInput/TextInputLabel/index.native.js b/src/components/TextInput/TextInputLabel/index.native.js
index afc2aa09c84e..eb0f8b17e8b7 100644
--- a/src/components/TextInput/TextInputLabel/index.native.js
+++ b/src/components/TextInput/TextInputLabel/index.native.js
@@ -1,7 +1,7 @@
import React, {useState} from 'react';
import {Animated} from 'react-native';
import * as styleConst from '@components/TextInput/styleConst';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TextInputLabelPropTypes from './TextInputLabelPropTypes';
function TextInputLabel(props) {
diff --git a/src/components/TextInput/index.js b/src/components/TextInput/index.js
index 27ca1d524eda..87db18754ed8 100644
--- a/src/components/TextInput/index.js
+++ b/src/components/TextInput/index.js
@@ -1,9 +1,9 @@
import React, {useEffect, useRef} from 'react';
import _ from 'underscore';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import DomUtils from '@libs/DomUtils';
import Visibility from '@libs/Visibility';
-import useThemeStyles from '@styles/useThemeStyles';
import BaseTextInput from './BaseTextInput';
import * as baseTextInputPropTypes from './BaseTextInput/baseTextInputPropTypes';
import * as styleConst from './styleConst';
diff --git a/src/components/TextInput/index.native.js b/src/components/TextInput/index.native.js
index 14591167a425..e5aba76957ad 100644
--- a/src/components/TextInput/index.native.js
+++ b/src/components/TextInput/index.native.js
@@ -1,6 +1,6 @@
import React, {forwardRef, useEffect} from 'react';
import {AppState, Keyboard} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import BaseTextInput from './BaseTextInput';
import * as baseTextInputPropTypes from './BaseTextInput/baseTextInputPropTypes';
diff --git a/src/components/TextLink.tsx b/src/components/TextLink.tsx
index 95c456ddc8e3..1a67e7bc4c5f 100644
--- a/src/components/TextLink.tsx
+++ b/src/components/TextLink.tsx
@@ -1,7 +1,7 @@
import React, {ForwardedRef, forwardRef, KeyboardEventHandler, MouseEventHandler} from 'react';
import {GestureResponderEvent, Text as RNText, StyleProp, TextStyle} from 'react-native';
import useEnvironment from '@hooks/useEnvironment';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
import Text, {TextProps} from './Text';
diff --git a/src/components/TextWithEllipsis/index.tsx b/src/components/TextWithEllipsis/index.tsx
index ee2ec72d1248..fda0d5ab576e 100644
--- a/src/components/TextWithEllipsis/index.tsx
+++ b/src/components/TextWithEllipsis/index.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {StyleProp, TextStyle, View, ViewStyle} from 'react-native';
import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
type TextWithEllipsisProps = {
/** Leading text before the ellipsis */
diff --git a/src/styles/illustrations/ThemeIllustrationsProvider.tsx b/src/components/ThemeIllustrationsProvider.tsx
similarity index 58%
rename from src/styles/illustrations/ThemeIllustrationsProvider.tsx
rename to src/components/ThemeIllustrationsProvider.tsx
index 423e0c1866b1..3b83a00960a4 100644
--- a/src/styles/illustrations/ThemeIllustrationsProvider.tsx
+++ b/src/components/ThemeIllustrationsProvider.tsx
@@ -1,8 +1,7 @@
import React, {useMemo} from 'react';
-import useThemePreference from '@styles/themes/useThemePreference';
-import DarkIllustrations from './dark';
-import LightIllustrations from './light';
-import ThemeIllustrationsContext from './ThemeIllustrationsContext';
+import useThemePreference from '@hooks/useThemePreference';
+import ThemeIllustrationsContext from '@styles/theme/context/ThemeIllustrationsContext';
+import Illustrations from '@styles/theme/illustrations';
type ThemeIllustrationsProviderProps = {
children: React.ReactNode;
@@ -11,7 +10,7 @@ type ThemeIllustrationsProviderProps = {
function ThemeIllustrationsProvider({children}: ThemeIllustrationsProviderProps) {
const themePreference = useThemePreference();
- const illustrations = useMemo(() => (themePreference === 'dark' ? DarkIllustrations : LightIllustrations), [themePreference]);
+ const illustrations = useMemo(() => Illustrations[themePreference], [themePreference]);
return {children};
}
diff --git a/src/styles/themes/ThemeProvider.tsx b/src/components/ThemeProvider.tsx
similarity index 74%
rename from src/styles/themes/ThemeProvider.tsx
rename to src/components/ThemeProvider.tsx
index 0d302b5ae056..34bc32be9c99 100644
--- a/src/styles/themes/ThemeProvider.tsx
+++ b/src/components/ThemeProvider.tsx
@@ -1,10 +1,10 @@
/* eslint-disable react/jsx-props-no-spreading */
import PropTypes from 'prop-types';
import React, {useMemo} from 'react';
-import ThemeContext from './ThemeContext';
-import themes from './themes';
-import {ThemePreferenceWithoutSystem} from './types';
-import useThemePreferenceWithStaticOverride from './useThemePreferenceWithStaticOverride';
+import useThemePreferenceWithStaticOverride from '@hooks/useThemePreferenceWithStaticOverride';
+import themes from '@styles/theme';
+import ThemeContext from '@styles/theme/context/ThemeContext';
+import {ThemePreferenceWithoutSystem} from '@styles/theme/types';
const propTypes = {
/** Rendered child component */
diff --git a/src/styles/ThemeStylesProvider.tsx b/src/components/ThemeStylesProvider.tsx
similarity index 75%
rename from src/styles/ThemeStylesProvider.tsx
rename to src/components/ThemeStylesProvider.tsx
index 766cb00bd09b..f0d25d9e4dde 100644
--- a/src/styles/ThemeStylesProvider.tsx
+++ b/src/components/ThemeStylesProvider.tsx
@@ -1,8 +1,8 @@
import React, {useMemo} from 'react';
-import stylesGenerator from './styles';
-import useTheme from './themes/useTheme';
-import ThemeStylesContext from './ThemeStylesContext';
-import createStyleUtils from './utils';
+import useTheme from '@hooks/useTheme';
+import stylesGenerator from '@styles/index';
+import ThemeStylesContext from '@styles/theme/context/ThemeStylesContext';
+import createStyleUtils from '@styles/utils';
type ThemeStylesProviderProps = React.PropsWithChildren;
diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js
index dbaf8ab23360..0e84b4beeb7c 100644
--- a/src/components/ThreeDotsMenu/index.js
+++ b/src/components/ThreeDotsMenu/index.js
@@ -8,8 +8,8 @@ import PopoverMenu from '@components/PopoverMenu';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Tooltip from '@components/Tooltip/PopoverAnchorTooltip';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ThreeDotsMenuItemPropTypes from './ThreeDotsMenuItemPropTypes';
@@ -111,7 +111,7 @@ function ThreeDotsMenu({iconTooltip, icon, iconFill, iconStyles, onIconPress, me
}}
ref={buttonRef}
style={[styles.touchableButtonImage, ...iconStyles]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate(iconTooltip)}
>
{},
+ defaultValue: '',
+};
+
+const AMOUNT_VIEW_ID = 'amountView';
+const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView';
+const NUM_PAD_VIEW_ID = 'numPadView';
+
+function insertAtPosition(originalString, newSubstring, selectionPositionFrom, selectionPositionTo) {
+ // Check for invalid positions
+ if (selectionPositionFrom < 0 || selectionPositionTo < 0 || selectionPositionFrom > originalString.length || selectionPositionTo > originalString.length) {
+ return;
+ }
+
+ // If the positions are the same, it means we're inserting at a point
+ if (selectionPositionFrom === selectionPositionTo) {
+ if (selectionPositionFrom === originalString.length) {
+ return originalString; // If the insertion point is at the end, simply return the original string
+ }
+ return originalString.slice(0, selectionPositionFrom) + newSubstring + originalString.slice(selectionPositionFrom);
+ }
+
+ // Replace the selected range
+ return originalString.slice(0, selectionPositionFrom) + newSubstring + originalString.slice(selectionPositionTo);
+}
+
+// if we need manually to move selection to the left we need to decrease both selection start and end by one
+function decreaseBothSelectionByOne({start, end}) {
+ if (start === 0) {
+ return {start: 0, end: 0};
+ }
+ return {start: start - 1, end: end - 1};
+}
+
+function replaceWithZeroAtPosition(originalString, position) {
+ if (position === 0 || position > 2) {
+ return originalString;
+ }
+ return `${originalString.slice(0, position - 1)}0${originalString.slice(position)}`;
+}
+
+function TimePicker({forwardedRef, defaultValue, onSubmit, onInputChange}) {
+ const {numberFormat, translate} = useLocalize();
+ const {isExtraSmallScreenHeight} = useWindowDimensions();
+ const styles = useThemeStyles();
+ const StyleUtils = useStyleUtils();
+ const value = DateUtils.extractTime12Hour(defaultValue);
+ const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen();
+
+ const [isError, setError] = useState(false);
+ const [selectionHour, setSelectionHour] = useState({start: 0, end: 0});
+ const [selectionMinute, setSelectionMinute] = useState({start: 2, end: 2}); // we focus it by default so need to have selection on the end
+ const [hours, setHours] = useState(() => DateUtils.get12HourTimeObjectFromDate(value).hour);
+ const [minute, setMinute] = useState(() => DateUtils.get12HourTimeObjectFromDate(value).minute);
+ const [amPmValue, setAmPmValue] = useState(() => DateUtils.get12HourTimeObjectFromDate(value).period);
+
+ const hourInputRef = useRef(null);
+ const minuteInputRef = useRef(null);
+
+ const focusMinuteInputOnFirstCharacter = useCallback(() => {
+ const cleanupTimer = setSelection({start: 0, end: 0}, minuteInputRef, setSelectionMinute);
+ return cleanupTimer;
+ }, []);
+ const focusHourInputOnLastCharacter = useCallback(() => {
+ setSelectionHour({start: 2, end: 2});
+ const timer = setTimeout(() => {
+ hourInputRef.current.focus();
+ }, 10);
+ return () => clearTimeout(timer);
+ }, []);
+
+ const validate = useCallback(
+ (time) => {
+ const isValid = DateUtils.isTimeAtLeastOneMinuteInFuture({timeString: time || `${hours}:${minute} ${amPmValue}`, dateTimeString: defaultValue});
+ setError(!isValid);
+ return isValid;
+ },
+ [hours, minute, amPmValue, defaultValue],
+ );
+
+ // This function receive value from hour input and validate it
+ // The valid format is HH(from 00 to 12). If the user input 9, it will be 09. If user try to change 09 to 19 it would skip the first character
+ const handleHourChange = (text) => {
+ const isOnlyNumericValue = /^\d+$/.test(text.trim());
+ // Skip if the user is pasting the text or use non numeric characters.
+ if (selectionHour.start !== selectionHour.end || !isOnlyNumericValue) {
+ return;
+ }
+ // Remove non-numeric characters.
+ const filteredText = text.replace(/[^0-9]/g, '');
+
+ let newHour = hours;
+ let newSelection = selectionHour.start;
+
+ // Case when the cursor is at the start.
+ if (selectionHour.start === 0) {
+ // Handle cases where the hour would be > 12.
+
+ // when you entering text the filteredText would consist of three numbers
+ const formattedText = `${filteredText[0]}${filteredText[2] || 0}`;
+ if (formattedText > 12 && formattedText <= 24) {
+ newHour = String(formattedText - 12).padStart(2, '0');
+ newSelection = 2;
+ setAmPmValue(CONST.TIME_PERIOD.PM);
+ } else if (formattedText > 24) {
+ newHour = `0${formattedText[1]}`;
+ newSelection = 2;
+ } else {
+ newHour = `${formattedText[0]}${formattedText[1]}`;
+ newSelection = 1;
+ }
+ } else if (selectionHour.start === 1) {
+ // Case when the cursor is at the second position.
+ const formattedText = `${filteredText[0]}${filteredText[1]}`;
+
+ if (filteredText.length < 2) {
+ // If we remove a value, prepend 0.
+ newHour = `0${text}`;
+ newSelection = 0;
+ // If the second digit is > 2, replace the hour with 0 and the second digit.
+ } else if (formattedText > 12 && formattedText <= 24) {
+ newHour = String(formattedText - 12).padStart(2, '0');
+ newSelection = 2;
+ setAmPmValue(CONST.TIME_PERIOD.PM);
+ } else if (formattedText > 24) {
+ newHour = `0${text[1]}`;
+ newSelection = 2;
+ } else {
+ newHour = `${text[0]}${text[1]}`;
+ setHours(newHour);
+ newSelection = 2;
+ }
+ } else if (selectionHour.start === 2 && selectionHour.end === 2) {
+ // Case when the cursor is at the end and no text is selected.
+ if (filteredText.length < 2) {
+ newHour = `${text}0`;
+ newSelection = 1;
+ } else {
+ newSelection = 2;
+ }
+ }
+
+ setHours(newHour);
+ setSelectionHour({start: newSelection, end: newSelection});
+ if (newSelection === 2) {
+ focusMinuteInputOnFirstCharacter();
+ }
+ };
+
+ // This function receive value from minute input and validate it
+ // The valid format is MM(from 00 to 59). If the user input 9, it will be 09. If user try to change 09 to 99 it would skip the character
+ const handleMinutesChange = (text) => {
+ const isOnlyNumericValue = /^\d+$/.test(text.trim());
+ // Skip if the user is pasting the text or use non numeric characters.
+ if (selectionMinute.start !== selectionMinute.end || !isOnlyNumericValue) {
+ return;
+ }
+
+ // Remove non-numeric characters.
+ const filteredText = text.replace(/[^0-9]/g, '');
+
+ let newMinute = minute;
+ let newSelection = selectionMinute.start;
+ // Case when user selects and replaces the text.
+ if (selectionMinute.start !== selectionMinute.end) {
+ // If the first digit is > 5, prepend 0.
+ if (filteredText.length === 1 && filteredText > 5) {
+ newMinute = `0${filteredText}`;
+ newSelection = 2;
+ // If the first digit is <= 5, append 0 at the end.
+ } else if (filteredText.length === 1 && filteredText <= 5) {
+ newMinute = `${filteredText}0`;
+ newSelection = 1;
+ } else {
+ newMinute = `${filteredText.slice(0, 2)}`;
+ newSelection = 2;
+ }
+ } else if (selectionMinute.start === 0) {
+ // Case when the cursor is at the start.
+ const formattedText = `${filteredText[0]}${filteredText[2] || 0}`;
+ if (text[0] >= 6) {
+ newMinute = `0${formattedText[1]}`;
+ newSelection = 2;
+ } else {
+ newMinute = `${formattedText[0]}${formattedText[1]}`;
+ newSelection = 1;
+ }
+ } else if (selectionMinute.start === 1) {
+ // Case when the cursor is at the second position.
+ // If we remove a value, prepend 0.
+ if (filteredText.length < 2) {
+ newMinute = `0${text}`;
+ newSelection = 0;
+ setSelectionHour({start: 2, end: 2});
+ hourInputRef.current.focus();
+ } else {
+ newMinute = `${text[0]}${text[1]}`;
+ newSelection = 2;
+ }
+ } else if (filteredText.length < 2) {
+ // Case when the cursor is at the end and no text is selected.
+ newMinute = `${text}0`;
+ newSelection = 1;
+ }
+
+ setMinute(newMinute);
+ setSelectionMinute({start: newSelection, end: newSelection});
+ };
+
+ /**
+ * Update amount with number or Backspace pressed for BigNumberPad.
+ * Validate new amount with decimal number regex up to 6 digits and 2 decimal digit to enable Next button
+ *
+ * @param {String} key
+ */
+ const updateAmountNumberPad = useCallback(
+ (key) => {
+ const isHourFocused = hourInputRef.current.isFocused();
+ const isMinuteFocused = minuteInputRef.current.isFocused();
+ if (!isHourFocused && !isMinuteFocused) {
+ minuteInputRef.current.focus();
+ }
+
+ if (key === '.') {
+ return;
+ }
+ if (key === '<' || key === 'Backspace') {
+ if (isHourFocused) {
+ const newHour = replaceWithZeroAtPosition(hours, selectionHour.start);
+ setHours(newHour);
+ setSelectionHour(decreaseBothSelectionByOne(selectionHour));
+ } else if (isMinuteFocused) {
+ if (selectionMinute.start === 0) {
+ focusHourInputOnLastCharacter();
+ return;
+ }
+ const newMinute = replaceWithZeroAtPosition(minute, selectionMinute.start);
+ setMinute(newMinute);
+ setSelectionMinute(decreaseBothSelectionByOne(selectionMinute));
+ }
+ return;
+ }
+ const trimmedKey = key.replace(/[^0-9]/g, '');
+
+ if (isHourFocused) {
+ handleHourChange(insertAtPosition(hours, trimmedKey, selectionHour.start, selectionHour.end));
+ } else if (isMinuteFocused) {
+ handleMinutesChange(insertAtPosition(minute, trimmedKey, selectionMinute.start, selectionMinute.end));
+ }
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [minute, hours, selectionHour, selectionMinute],
+ );
+
+ useEffect(() => {
+ // we implement this to ensure the hour input focuses on the first character upon initial focus
+ // https://github.com/facebook/react-native/issues/20214
+ setSelectionHour({start: 0, end: 0});
+ }, []);
+
+ const arrowConfig = useMemo(
+ () => ({
+ shouldPreventDefault: false,
+ }),
+ [],
+ );
+
+ const arrowLeftCallback = useCallback(() => {
+ const isMinuteFocused = minuteInputRef.current.isFocused();
+ if (isMinuteFocused && selectionMinute.start === 0) {
+ focusHourInputOnLastCharacter();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [selectionHour, selectionMinute]);
+ const arrowRightCallback = useCallback(() => {
+ const isHourFocused = hourInputRef.current.isFocused();
+
+ if (isHourFocused && selectionHour.start === 2) {
+ focusMinuteInputOnFirstCharacter();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [selectionHour, selectionMinute]);
+
+ useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ARROW_LEFT, arrowLeftCallback, arrowConfig);
+ useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ARROW_RIGHT, arrowRightCallback, arrowConfig);
+
+ const handleFocusOnBackspace = useCallback(
+ (e) => {
+ if (selectionMinute.start !== 0 || e.key !== 'Backspace') {
+ return;
+ }
+ hourInputRef.current.focus();
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [selectionMinute.start],
+ );
+
+ const {styleForAM, styleForPM} = StyleUtils.getStatusAMandPMButtonStyle(amPmValue);
+
+ const numberPad = useCallback(() => {
+ if (!canUseTouchScreen) {
+ return null;
+ }
+ return (
+
+ );
+ }, [canUseTouchScreen, updateAmountNumberPad]);
+
+ useEffect(() => {
+ onInputChange(`${hours}:${minute} ${amPmValue}`);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [hours, minute, amPmValue]);
+
+ const handleSubmit = () => {
+ const time = `${hours}:${minute} ${amPmValue}`;
+ const isValid = validate(time);
+
+ if (isValid) {
+ onSubmit(time);
+ }
+ };
+
+ return (
+
+
+
+ {
+ if (typeof forwardedRef === 'function') {
+ forwardedRef({refHour: ref, minuteRef: minuteInputRef.current});
+ } else if (forwardedRef && _.has(forwardedRef, 'current')) {
+ // eslint-disable-next-line no-param-reassign
+ forwardedRef.current = {hourRef: ref, minuteRef: minuteInputRef.current};
+ }
+ hourInputRef.current = ref;
+ }}
+ onSelectionChange={(e) => {
+ setSelectionHour(e.nativeEvent.selection);
+ }}
+ style={styles.timePickerInput}
+ containerStyles={[styles.timePickerHeight100]}
+ selection={selectionHour}
+ showSoftInputOnFocus={false}
+ />
+ {CONST.COLON}
+ {
+ if (typeof forwardedRef === 'function') {
+ forwardedRef({refHour: hourInputRef.current, minuteRef: ref});
+ } else if (forwardedRef && _.has(forwardedRef, 'current')) {
+ // eslint-disable-next-line no-param-reassign
+ minuteInputRef.current = {hourRef: hourInputRef.current, minuteInputRef: ref};
+ }
+ minuteInputRef.current = ref;
+ }}
+ onSelectionChange={(e) => {
+ setSelectionMinute(e.nativeEvent.selection);
+ }}
+ style={styles.timePickerInput}
+ containerStyles={[styles.timePickerHeight100]}
+ selection={selectionMinute}
+ showSoftInputOnFocus={false}
+ />
+
+
+
+
+ {isError ? (
+
+ ) : (
+
+ )}
+
+ {numberPad()}
+
+
+
+ );
+}
+
+TimePicker.propTypes = propTypes;
+TimePicker.defaultProps = defaultProps;
+TimePicker.displayName = 'TimePicker';
+
+const TimePickerWithRef = React.forwardRef((props, ref) => (
+
+));
+
+TimePickerWithRef.displayName = 'TimePickerWithRef';
+
+export default TimePickerWithRef;
diff --git a/src/components/TimePicker/setSelection.ios.ts b/src/components/TimePicker/setSelection.ios.ts
new file mode 100644
index 000000000000..0d1dfc004bc7
--- /dev/null
+++ b/src/components/TimePicker/setSelection.ios.ts
@@ -0,0 +1,8 @@
+import {RefObject} from 'react';
+import {TextInput} from 'react-native';
+
+export default function setSelection(value: {start: number; end: number}, ref: RefObject) {
+ ref.current?.focus();
+ ref.current?.setNativeProps({selection: value});
+ return () => {};
+}
diff --git a/src/components/TimePicker/setSelection.ts b/src/components/TimePicker/setSelection.ts
new file mode 100644
index 000000000000..36304b408f29
--- /dev/null
+++ b/src/components/TimePicker/setSelection.ts
@@ -0,0 +1,18 @@
+// setSelection.ts
+import {RefObject} from 'react';
+import {TextInput} from 'react-native';
+
+const setSelection = (value: {start: number; end: number}, ref: RefObject, setSelectionCallback: (value: {start: number; end: number}) => void): (() => void) => {
+ ref.current?.focus();
+
+ const timer = setTimeout(() => {
+ setSelectionCallback(value);
+ }, 10);
+
+ // Return the cleanup function
+ return () => {
+ clearTimeout(timer);
+ };
+};
+
+export default setSelection;
diff --git a/src/components/Tooltip/TooltipRenderedOnPageBody.tsx b/src/components/Tooltip/TooltipRenderedOnPageBody.tsx
index 2ed885c9d3d7..4549f48501bf 100644
--- a/src/components/Tooltip/TooltipRenderedOnPageBody.tsx
+++ b/src/components/Tooltip/TooltipRenderedOnPageBody.tsx
@@ -2,8 +2,8 @@ import React, {useEffect, useLayoutEffect, useMemo, useRef, useState} from 'reac
import ReactDOM from 'react-dom';
import {Animated, View} from 'react-native';
import Text from '@components/Text';
+import useStyleUtils from '@hooks/useStyleUtils';
import Log from '@libs/Log';
-import useStyleUtils from '@styles/useStyleUtils';
import textRef from '@src/types/utils/textRef';
import viewRef from '@src/types/utils/viewRef';
import TooltipProps from './types';
diff --git a/src/components/UnorderedList.tsx b/src/components/UnorderedList.tsx
index a51cefce9ce6..a2b836bd4d80 100644
--- a/src/components/UnorderedList.tsx
+++ b/src/components/UnorderedList.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import {View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import Text from './Text';
type UnorderedListProps = {
diff --git a/src/components/UnreadActionIndicator.tsx b/src/components/UnreadActionIndicator.tsx
index b34f962e57bd..f422ae24bd4f 100755
--- a/src/components/UnreadActionIndicator.tsx
+++ b/src/components/UnreadActionIndicator.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import Text from './Text';
diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js
index 508bc6f8426c..5e88a7994e51 100644
--- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js
+++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js
@@ -7,10 +7,10 @@ import Avatar from '@components/Avatar';
import {usePersonalDetails} from '@components/OnyxProvider';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {defaultProps, propTypes} from './userDetailsTooltipPropTypes';
@@ -20,7 +20,7 @@ function BaseUserDetailsTooltip(props) {
const personalDetails = usePersonalDetails();
const userDetails = lodashGet(personalDetails, props.accountID, props.fallbackUserDetails);
- let userDisplayName = ReportUtils.getDisplayNameForParticipant(props.accountID);
+ let userDisplayName = ReportUtils.getDisplayNameForParticipant(props.accountID) || (userDetails.displayName ? userDetails.displayName.trim() : '');
let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : '';
let userAvatar = userDetails.avatar;
let userAccountID = props.accountID;
diff --git a/src/components/ValidateCode/ExpiredValidateCodeModal.js b/src/components/ValidateCode/ExpiredValidateCodeModal.js
index caeef8a14a0a..cb880a0a2844 100644
--- a/src/components/ValidateCode/ExpiredValidateCodeModal.js
+++ b/src/components/ValidateCode/ExpiredValidateCodeModal.js
@@ -5,8 +5,8 @@ import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/components/ValidateCode/JustSignedInModal.js b/src/components/ValidateCode/JustSignedInModal.js
index 0ae4c882784c..fedb92c49ee3 100644
--- a/src/components/ValidateCode/JustSignedInModal.js
+++ b/src/components/ValidateCode/JustSignedInModal.js
@@ -6,8 +6,8 @@ import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/components/ValidateCode/ValidateCodeModal.js b/src/components/ValidateCode/ValidateCodeModal.js
index 58f9b24e3c91..a2fea513f851 100644
--- a/src/components/ValidateCode/ValidateCodeModal.js
+++ b/src/components/ValidateCode/ValidateCodeModal.js
@@ -10,8 +10,8 @@ import * as Illustrations from '@components/Icon/Illustrations';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import * as Session from '@userActions/Session';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/components/ValuePicker/ValueSelectorModal.js b/src/components/ValuePicker/ValueSelectorModal.js
index b70bcc5cbbb7..edc5a48d0bb3 100644
--- a/src/components/ValuePicker/ValueSelectorModal.js
+++ b/src/components/ValuePicker/ValueSelectorModal.js
@@ -5,7 +5,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Modal from '@components/Modal';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/components/ValuePicker/index.js b/src/components/ValuePicker/index.js
index 6eb20d1bde6a..b5ddaa7dcb73 100644
--- a/src/components/ValuePicker/index.js
+++ b/src/components/ValuePicker/index.js
@@ -5,8 +5,8 @@ import {View} from 'react-native';
import FormHelpMessage from '@components/FormHelpMessage';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import refPropTypes from '@components/refPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import ValueSelectorModal from './ValueSelectorModal';
diff --git a/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js b/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js
index 4d5affafc407..54e7309ee48b 100755
--- a/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js
+++ b/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js
@@ -12,9 +12,9 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed
import Tooltip from '@components/Tooltip/PopoverAnchorTooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
@@ -103,7 +103,7 @@ function BaseVideoChatButtonAndMenu(props) {
})}
style={styles.touchableButtonImage}
accessibilityLabel={props.translate('videoChatButtonAndMenu.tooltip')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
;
/** The text to display in the subtitle of the section */
- subtitle: PropTypes.string,
+ subtitle: string;
/** The text to display in the title of the section */
- title: PropTypes.string.isRequired,
-};
-
-const defaultProps = {
- children: null,
- icon: null,
- subtitle: null,
+ title: string;
};
-function WalletSection({children, icon, subtitle, title}) {
+function WalletSection({children, icon, subtitle, title}: WalletSectionProps) {
const styles = useThemeStyles();
return (
void;
+};
+
+export default function useAutoFocusInput(): UseAutoFocusInput {
const [isInputInitialized, setIsInputInitialized] = useState(false);
const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
+ // @ts-expect-error TODO: Remove this when Expensify.js is migrated.
const {isSplashHidden} = useContext(Expensify.SplashScreenHiddenContext);
- const inputRef = useRef(null);
- const focusTimeoutRef = useRef(null);
+ const inputRef = useRef(null);
+ const focusTimeoutRef = useRef(null);
useEffect(() => {
if (!isScreenTransitionEnded || !isInputInitialized || !inputRef.current || !isSplashHidden) {
return;
}
InteractionManager.runAfterInteractions(() => {
- inputRef.current.focus();
+ inputRef.current?.focus();
setIsScreenTransitionEnded(false);
});
}, [isScreenTransitionEnded, isInputInitialized, isSplashHidden]);
@@ -38,7 +43,7 @@ export default function useAutoFocusInput() {
}, []),
);
- const inputCallbackRef = (ref) => {
+ const inputCallbackRef = (ref: TextInput | null) => {
inputRef.current = ref;
setIsInputInitialized(true);
};
diff --git a/src/hooks/useDelayedInputFocus.js b/src/hooks/useDelayedInputFocus.ts
similarity index 62%
rename from src/hooks/useDelayedInputFocus.js
rename to src/hooks/useDelayedInputFocus.ts
index 7a4a64104e48..d062f8a03d25 100644
--- a/src/hooks/useDelayedInputFocus.js
+++ b/src/hooks/useDelayedInputFocus.ts
@@ -1,19 +1,17 @@
import {useFocusEffect} from '@react-navigation/native';
-import {useCallback, useRef} from 'react';
+import {MutableRefObject, useCallback, useRef} from 'react';
+import {TextInput} from 'react-native';
import CONST from '@src/CONST';
/**
* Focus a text input when a screen is navigated to, after the specified time delay has elapsed.
- *
- * @param {Object} inputRef
- * @param {Number} [delay]
*/
-export default function useDelayedInputFocus(inputRef, delay = CONST.ANIMATED_TRANSITION) {
- const timeoutRef = useRef(null);
+export default function useDelayedInputFocus(inputRef: MutableRefObject, delay: number = CONST.ANIMATED_TRANSITION) {
+ const timeoutRef = useRef(null);
useFocusEffect(
useCallback(() => {
- timeoutRef.current = setTimeout(() => inputRef.current && inputRef.current.focus(), delay);
+ timeoutRef.current = setTimeout(() => inputRef.current?.focus(), delay);
return () => {
if (!timeoutRef.current) {
return;
diff --git a/src/hooks/useHandleExceedMaxCommentLength.ts b/src/hooks/useHandleExceedMaxCommentLength.ts
new file mode 100644
index 000000000000..9700999bb004
--- /dev/null
+++ b/src/hooks/useHandleExceedMaxCommentLength.ts
@@ -0,0 +1,27 @@
+import _ from 'lodash';
+import {useCallback, useMemo, useState} from 'react';
+import * as ReportUtils from '@libs/ReportUtils';
+import CONST from '@src/CONST';
+
+const useHandleExceedMaxCommentLength = () => {
+ const [hasExceededMaxCommentLength, setHasExceededMaxCommentLength] = useState(false);
+
+ const handleValueChange = useCallback(
+ (value: string) => {
+ if (ReportUtils.getCommentLength(value) <= CONST.MAX_COMMENT_LENGTH) {
+ if (hasExceededMaxCommentLength) {
+ setHasExceededMaxCommentLength(false);
+ }
+ return;
+ }
+ setHasExceededMaxCommentLength(true);
+ },
+ [hasExceededMaxCommentLength],
+ );
+
+ const validateCommentMaxLength = useMemo(() => _.debounce(handleValueChange, 1500), [handleValueChange]);
+
+ return {hasExceededMaxCommentLength, validateCommentMaxLength};
+};
+
+export default useHandleExceedMaxCommentLength;
diff --git a/src/hooks/useInitialWindowDimensions/index.js b/src/hooks/useInitialWindowDimensions/index.ts
similarity index 80%
rename from src/hooks/useInitialWindowDimensions/index.js
rename to src/hooks/useInitialWindowDimensions/index.ts
index 5878c8b3371f..e0882e820e9b 100644
--- a/src/hooks/useInitialWindowDimensions/index.js
+++ b/src/hooks/useInitialWindowDimensions/index.ts
@@ -1,14 +1,24 @@
// eslint-disable-next-line no-restricted-imports
import {useEffect, useState} from 'react';
-import {Dimensions} from 'react-native';
+import {Dimensions, type ScaledSize} from 'react-native';
+
+type InitialWindowDimensions = {
+ initialWidth: number;
+ initialHeight: number;
+};
+
+type NewDimensions = {
+ window: ScaledSize;
+ screen: ScaledSize;
+};
/**
* A convenience hook that provides initial size (width and height).
* An initial height allows to know the real height of window,
* while the standard useWindowDimensions hook return the height minus Virtual keyboard height
- * @returns {Object} with information about initial width and height
+ * @returns with information about initial width and height
*/
-export default function () {
+export default function (): InitialWindowDimensions {
const [dimensions, setDimensions] = useState(() => {
const window = Dimensions.get('window');
const screen = Dimensions.get('screen');
@@ -22,7 +32,7 @@ export default function () {
});
useEffect(() => {
- const onDimensionChange = (newDimensions) => {
+ const onDimensionChange = (newDimensions: NewDimensions) => {
const {window, screen} = newDimensions;
setDimensions((oldState) => {
diff --git a/src/hooks/useIsScrollBarVisible/index.native.ts b/src/hooks/useIsScrollBarVisible/index.native.ts
new file mode 100644
index 000000000000..a461e1b7b074
--- /dev/null
+++ b/src/hooks/useIsScrollBarVisible/index.native.ts
@@ -0,0 +1,7 @@
+/**
+ * Native doesn't have the DOM, so we just return null.
+ *
+ */
+const useIsScrollBarVisible = () => null;
+
+export default useIsScrollBarVisible;
diff --git a/src/hooks/useIsScrollBarVisible/index.ts b/src/hooks/useIsScrollBarVisible/index.ts
new file mode 100644
index 000000000000..4ab3a7bb24db
--- /dev/null
+++ b/src/hooks/useIsScrollBarVisible/index.ts
@@ -0,0 +1,28 @@
+import {useCallback, useEffect, useState} from 'react';
+
+const useIsScrollBarVisible = (ref: React.RefObject, value: string) => {
+ const [isScrollBarVisible, setIsScrollBarVisible] = useState(false);
+
+ const handleResize = useCallback(() => {
+ if (!ref.current) {
+ return;
+ }
+ const {scrollHeight, clientHeight} = ref.current;
+ setIsScrollBarVisible(scrollHeight > clientHeight);
+ }, [ref]);
+
+ useEffect(() => {
+ if (!ref.current || !('ResizeObserver' in (window || {}))) {
+ return;
+ }
+
+ const resizeObserver = new ResizeObserver(handleResize);
+ resizeObserver.observe(ref.current);
+ return () => {
+ resizeObserver.disconnect();
+ };
+ }, [handleResize, ref, value]);
+ return isScrollBarVisible;
+};
+
+export default useIsScrollBarVisible;
diff --git a/src/styles/useStyleUtils.ts b/src/hooks/useStyleUtils.ts
similarity index 83%
rename from src/styles/useStyleUtils.ts
rename to src/hooks/useStyleUtils.ts
index aadb3f884220..8e6ad31396d5 100644
--- a/src/styles/useStyleUtils.ts
+++ b/src/hooks/useStyleUtils.ts
@@ -1,5 +1,5 @@
import {useContext} from 'react';
-import ThemeStylesContext from './ThemeStylesContext';
+import ThemeStylesContext from '@styles/theme/context/ThemeStylesContext';
function useStyleUtils() {
const themeStylesContext = useContext(ThemeStylesContext);
diff --git a/src/hooks/useTabNavigatorFocus/index.js b/src/hooks/useTabNavigatorFocus/index.ts
similarity index 83%
rename from src/hooks/useTabNavigatorFocus/index.js
rename to src/hooks/useTabNavigatorFocus/index.ts
index f83ec5bd9270..9138cbbdab48 100644
--- a/src/hooks/useTabNavigatorFocus/index.js
+++ b/src/hooks/useTabNavigatorFocus/index.ts
@@ -1,8 +1,17 @@
import {useTabAnimation} from '@react-navigation/material-top-tabs';
import {useIsFocused} from '@react-navigation/native';
import {useEffect, useState} from 'react';
+import {Animated} from 'react-native';
import DomUtils from '@libs/DomUtils';
+type UseTabNavigatorFocusParams = {
+ tabIndex: number;
+};
+
+type PositionAnimationListenerCallback = {
+ value: number;
+};
+
/**
* Custom React hook to determine the focus status of a tab in a Material Top Tab Navigator.
* It evaluates whether the current tab is focused based on the tab's animation position and
@@ -17,15 +26,16 @@ import DomUtils from '@libs/DomUtils';
* might not be used within a Material Top Tabs Navigator context. Proper usage should ensure that
* this hook is only used where appropriate.
*
- * @param {Object} params - The parameters object.
- * @param {Number} params.tabIndex - The index of the tab for which focus status is being determined.
- * @returns {Boolean} Returns `true` if the tab is both animation-focused and screen-focused, otherwise `false`.
+ * @param params - The parameters object.
+ * @param params.tabIndex - The index of the tab for which focus status is being determined.
+ * @returns Returns `true` if the tab is both animation-focused and screen-focused, otherwise `false`.
*
* @example
* const isTabFocused = useTabNavigatorFocus({ tabIndex: 1 });
*/
-function useTabNavigatorFocus({tabIndex}) {
- let tabPositionAnimation = null;
+function useTabNavigatorFocus({tabIndex}: UseTabNavigatorFocusParams): boolean {
+ let tabPositionAnimation: Animated.AnimatedInterpolation | null = null;
+
try {
// Retrieve the animation value from the tab navigator, which ranges from 0 to the total number of pages displayed.
// Even a minimal scroll towards the camera page (e.g., a value of 0.001 at start) should activate the camera for immediate responsiveness.
@@ -46,7 +56,7 @@ function useTabNavigatorFocus({tabIndex}) {
}
const index = Number(tabIndex);
- const listenerId = tabPositionAnimation.addListener(({value}) => {
+ const listenerId = tabPositionAnimation.addListener(({value}: PositionAnimationListenerCallback) => {
// Activate camera as soon the index is animating towards the `tabIndex`
DomUtils.requestAnimationFrame(() => {
setIsTabFocused(value > index - 1 && value < index + 1);
@@ -56,6 +66,7 @@ function useTabNavigatorFocus({tabIndex}) {
// We need to get the position animation value on component initialization to determine
// if the tab is focused or not. Since it's an Animated.Value the only synchronous way
// to retrieve the value is to use a private method.
+ // @ts-expect-error -- __getValue is a private method
// eslint-disable-next-line no-underscore-dangle
const initialTabPositionValue = tabPositionAnimation.__getValue();
diff --git a/src/styles/themes/useTheme.ts b/src/hooks/useTheme.ts
similarity index 72%
rename from src/styles/themes/useTheme.ts
rename to src/hooks/useTheme.ts
index adeaffbcae8a..966e9b499e2f 100644
--- a/src/styles/themes/useTheme.ts
+++ b/src/hooks/useTheme.ts
@@ -1,6 +1,6 @@
import {useContext} from 'react';
-import ThemeContext from './ThemeContext';
-import {type ThemeColors} from './types';
+import ThemeContext from '@styles/theme/context/ThemeContext';
+import {type ThemeColors} from '@styles/theme/types';
function useTheme(): ThemeColors {
const theme = useContext(ThemeContext);
diff --git a/src/styles/illustrations/useThemeIllustrations.ts b/src/hooks/useThemeIllustrations.ts
similarity index 81%
rename from src/styles/illustrations/useThemeIllustrations.ts
rename to src/hooks/useThemeIllustrations.ts
index 32f986dc655a..5bc07185f882 100644
--- a/src/styles/illustrations/useThemeIllustrations.ts
+++ b/src/hooks/useThemeIllustrations.ts
@@ -1,5 +1,5 @@
import {useContext} from 'react';
-import ThemeIllustrationsContext from './ThemeIllustrationsContext';
+import ThemeIllustrationsContext from '@styles/theme/context/ThemeIllustrationsContext';
function useThemeIllustrations() {
const illustrations = useContext(ThemeIllustrationsContext);
diff --git a/src/styles/themes/useThemePreference.ts b/src/hooks/useThemePreference.ts
similarity index 51%
rename from src/styles/themes/useThemePreference.ts
rename to src/hooks/useThemePreference.ts
index ac87e2488b31..5d3ec4c3a860 100644
--- a/src/styles/themes/useThemePreference.ts
+++ b/src/hooks/useThemePreference.ts
@@ -1,26 +1,20 @@
import {useContext, useEffect, useState} from 'react';
-import {Appearance, ColorSchemeName} from 'react-native';
+import {useColorScheme} from 'react-native';
import {PreferredThemeContext} from '@components/OnyxProvider';
+import {ThemePreferenceWithoutSystem} from '@styles/theme/types';
import CONST from '@src/CONST';
-import {ThemePreferenceWithoutSystem} from './types';
function useThemePreference() {
- const [themePreference, setThemePreference] = useState(CONST.THEME.DEFAULT);
- const [systemTheme, setSystemTheme] = useState();
+ const [themePreference, setThemePreference] = useState(CONST.THEME.FALLBACK);
const preferredThemeFromStorage = useContext(PreferredThemeContext);
-
- useEffect(() => {
- // This is used for getting the system theme, that can be set in the OS's theme settings. This will always return either "light" or "dark" and will update automatically if the OS theme changes.
- const systemThemeSubscription = Appearance.addChangeListener(({colorScheme}) => setSystemTheme(colorScheme));
- return () => systemThemeSubscription.remove();
- }, []);
+ const systemTheme = useColorScheme();
useEffect(() => {
const theme = preferredThemeFromStorage ?? CONST.THEME.DEFAULT;
// If the user chooses to use the device theme settings, we need to set the theme preference to the system theme
if (theme === CONST.THEME.SYSTEM) {
- setThemePreference(systemTheme ?? CONST.THEME.DEFAULT);
+ setThemePreference(systemTheme ?? CONST.THEME.FALLBACK);
} else {
setThemePreference(theme);
}
diff --git a/src/styles/themes/useThemePreferenceWithStaticOverride.ts b/src/hooks/useThemePreferenceWithStaticOverride.ts
similarity index 90%
rename from src/styles/themes/useThemePreferenceWithStaticOverride.ts
rename to src/hooks/useThemePreferenceWithStaticOverride.ts
index b447740a0de1..4619da1966ce 100644
--- a/src/styles/themes/useThemePreferenceWithStaticOverride.ts
+++ b/src/hooks/useThemePreferenceWithStaticOverride.ts
@@ -1,4 +1,4 @@
-import {ThemePreferenceWithoutSystem} from './types';
+import {ThemePreferenceWithoutSystem} from '@styles/theme/types';
import useThemePreference from './useThemePreference';
const useThemePreferenceWithStaticOverride = (staticThemePreference: ThemePreferenceWithoutSystem | undefined) => {
diff --git a/src/styles/useThemeStyles.ts b/src/hooks/useThemeStyles.ts
similarity index 83%
rename from src/styles/useThemeStyles.ts
rename to src/hooks/useThemeStyles.ts
index 164806a908e4..05f36ff52cc5 100644
--- a/src/styles/useThemeStyles.ts
+++ b/src/hooks/useThemeStyles.ts
@@ -1,5 +1,5 @@
import {useContext} from 'react';
-import ThemeStylesContext from './ThemeStylesContext';
+import ThemeStylesContext from '@styles/theme/context/ThemeStylesContext';
function useThemeStyles() {
const themeStylesContext = useContext(ThemeStylesContext);
diff --git a/src/languages/en.ts b/src/languages/en.ts
index ee642dd8f333..644655bf4e9f 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -200,6 +200,8 @@ export default {
characterLimit: ({limit}: CharacterLimitParams) => `Exceeds the maximum length of ${limit} characters`,
characterLimitExceedCounter: ({length, limit}) => `Character limit exceeded (${length}/${limit})`,
dateInvalid: 'Please select a valid date',
+ invalidDateShouldBeFuture: 'Please choose today or a future date.',
+ invalidTimeShouldBeFuture: 'Please choose a time at least one minute ahead.',
invalidCharacter: 'Invalid character',
enterMerchant: 'Enter a merchant name',
enterAmount: 'Enter an amount',
@@ -269,6 +271,8 @@ export default {
kilometers: 'kilometers',
recent: 'Recent',
all: 'All',
+ am: 'AM',
+ pm: 'PM',
tbd: 'TBD',
selectCurrency: 'Select a currency',
card: 'Card',
@@ -1164,14 +1168,25 @@ export default {
},
statusPage: {
status: 'Status',
- setStatusTitle: 'Set your status',
statusExplanation: "Add an emoji to give your colleagues and friends an easy way to know what's going on. You can optionally add a message too!",
today: 'Today',
clearStatus: 'Clear status',
save: 'Save',
message: 'Message',
+ timePeriods: {
+ never: 'Never',
+ thirtyMinutes: '30 minutes',
+ oneHour: '1 hour',
+ afterToday: 'Today',
+ afterWeek: 'A week',
+ custom: 'Custom',
+ },
untilTomorrow: 'Until tomorrow',
untilTime: ({time}: UntilTimeParams) => `Until ${time}`,
+ date: 'Date',
+ time: 'Time',
+ clearAfter: 'Clear after',
+ whenClearStatus: 'When should we clear your status?',
},
stepCounter: ({step, total, text}: StepCounterParams) => {
let result = `Step ${step}`;
@@ -1266,8 +1281,10 @@ export default {
tryAgain: 'Try again',
verifyIdentity: 'Verify identity',
genericError: 'There was an error while processing this step. Please try again.',
- cameraPermissionsNotGranted: 'Camera permissions not granted',
- cameraRequestMessage: 'You have not granted us camera access. We need access to complete verification.',
+ cameraPermissionsNotGranted: 'Enable camera access',
+ cameraRequestMessage: 'We need access to your camera to complete bank account verification. Please enable via Settings > New Expensify.',
+ microphonePermissionsNotGranted: 'Enable microphone access',
+ microphoneRequestMessage: 'We need access to your microphone to complete bank account verification. Please enable via Settings > New Expensify.',
originalDocumentNeeded: 'Please upload an original image of your ID rather than a screenshot or scanned image.',
documentNeedsBetterQuality: 'Your ID appears to be damaged or has missing security features. Please upload an original image of an undamaged ID that is entirely visible.',
imageNeedsBetterQuality: "There's an issue with the image quality of your ID. Please upload a new image where your entire ID can be seen clearly.",
@@ -1475,6 +1492,8 @@ export default {
companyCards: 'Company credit cards',
reimbursements: 'Easy reimbursements',
},
+ notFound: 'No workspace found',
+ description: 'Rooms are a great place to discuss and work with multiple people. To begin collaborating, create or join a workspace',
},
new: {
newWorkspace: 'New workspace',
@@ -1971,31 +1990,30 @@ export default {
buttonText1: 'Start a chat, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Start a chat, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `Get paid to talk to your friends! Start a chat with a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `Get paid to talk to your friends! Start a chat with a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST]: {
buttonText1: 'Request money, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Request money, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `It pays to get paid! Request money from a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `It pays to get paid! Request money from a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY]: {
buttonText1: 'Send money, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Send money, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `You gotta send money to make money! Send money to a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
+ body: `You gotta send money to make money! Send money to a new Expensify account and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
buttonText1: 'Invite a friend, ',
buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
header: `Invite a friend, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `Send your Expensify invite link to a friend or anyone else you know who spends too much time on expenses. When they start an annual subscription, you'll get $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
+ body: 'Be the first to invite a friend (or anyone else) to Expensify and get $250 if they become an Expensify customer. Share your invite link by text, email, or post it on social media!',
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE]: {
buttonText1: `Get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Get $${CONST.REFERRAL_PROGRAM.REVENUE} for every referral`,
- body1: 'If you know anyone who’s spending too much time on expenses (literally anyone – your neighbor, your boss, your friend in accounting), send them your Expensify referral link:',
- body2: `When they start an annual subscription, you’ll get $${CONST.REFERRAL_PROGRAM.REVENUE}. Easy as that.`,
+ header: `Invite a friend, get $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Be the first to invite a friend (or anyone else) to Expensify and get $${CONST.REFERRAL_PROGRAM.REVENUE} if they become an Expensify customer. Share your invite link by text, email, or post it on social media!`,
},
copyReferralLink: 'Copy invite link',
},
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 10401d4822f7..6ecde0f44c55 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -190,6 +190,8 @@ export default {
characterLimit: ({limit}: CharacterLimitParams) => `Supera el límite de ${limit} caracteres`,
characterLimitExceedCounter: ({length, limit}) => `Se superó el límite de caracteres (${length}/${limit})`,
dateInvalid: 'Por favor, selecciona una fecha válida',
+ invalidDateShouldBeFuture: 'Por favor, elige una fecha igual o posterior a hoy',
+ invalidTimeShouldBeFuture: 'Por favor, elige una hora al menos un minuto en el futuro',
invalidCharacter: 'Carácter invalido',
enterMerchant: 'Introduce un comerciante',
enterAmount: 'Introduce un importe',
@@ -259,6 +261,8 @@ export default {
kilometers: 'kilómetros',
recent: 'Reciente',
all: 'Todo',
+ am: 'AM',
+ pm: 'PM',
tbd: 'Por determinar',
selectCurrency: 'Selecciona una moneda',
card: 'Tarjeta',
@@ -1165,12 +1169,19 @@ export default {
},
statusPage: {
status: 'Estado',
- setStatusTitle: 'Establece tu estado',
statusExplanation: 'Agrega un emoji para que tus colegas y amigos puedan saber fácilmente qué está pasando. ¡También puedes agregar un mensaje opcionalmente!',
today: 'Hoy',
clearStatus: 'Borrar estado',
save: 'Guardar',
message: 'Mensaje',
+ timePeriods: {
+ never: 'Nunca',
+ thirtyMinutes: '30 minutos',
+ oneHour: '1 hora',
+ afterToday: 'Hoy',
+ afterWeek: 'Una semana',
+ custom: 'Personalizado',
+ },
untilTomorrow: 'Hasta mañana',
untilTime: ({time}: UntilTimeParams) => {
// Check for HH:MM AM/PM format and starts with '01:'
@@ -1188,6 +1199,10 @@ export default {
// Default case
return `Hasta ${time}`;
},
+ date: 'Fecha',
+ time: 'Hora',
+ clearAfter: 'Borrar después',
+ whenClearStatus: '¿Cuándo deberíamos borrar tu estado?',
},
stepCounter: ({step, total, text}: StepCounterParams) => {
let result = `Paso ${step}`;
@@ -1285,8 +1300,11 @@ export default {
tryAgain: 'Intentar otra vez',
verifyIdentity: 'Verificar identidad',
genericError: 'Hubo un error al procesar este paso. Inténtalo de nuevo.',
- cameraPermissionsNotGranted: 'No has habilitado los permisos para acceder a la cámara',
- cameraRequestMessage: 'No has habilitado los permisos para acceder a la cámara. Necesitamos acceso para completar la verificaciôn.',
+ cameraPermissionsNotGranted: 'Permiso para acceder a la cámara',
+ cameraRequestMessage: 'Necesitamos acceso a tu cámara para completar la verificación de tu cuenta de banco. Por favor habilita los permisos en Configuración > Nuevo Expensify.',
+ microphonePermissionsNotGranted: 'Permiso para acceder al micrófono',
+ microphoneRequestMessage:
+ 'Necesitamos acceso a tu micrófono para completar la verificación de tu cuenta de banco. Por favor habilita los permisos en Configuración > Nuevo Expensify.',
originalDocumentNeeded: 'Por favor, sube una imagen original de tu identificación en lugar de una captura de pantalla o imagen escaneada.',
documentNeedsBetterQuality:
'Parece que tu identificación esta dañado o le faltan características de seguridad. Por favor, sube una imagen de tu documento sin daños y que se vea completamente.',
@@ -1497,6 +1515,8 @@ export default {
companyCards: 'Tarjetas de crédito corporativas',
reimbursements: 'Reembolsos fáciles',
},
+ notFound: 'No se encontró ningún espacio de trabajo',
+ description: 'Las salas son un gran lugar para discutir y trabajar con varias personas. Para comenzar a colaborar, cree o únase a un espacio de trabajo',
},
new: {
newWorkspace: 'Nuevo espacio de trabajo',
@@ -2457,31 +2477,30 @@ export default {
buttonText1: 'Inicia un chat y ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `Inicia un chat y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Gana dinero por hablar con tus amigos! Inicia un chat con una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Gana dinero por hablar con tus amigos! Inicia un chat con una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST]: {
buttonText1: 'Pide dinero, ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `Pide dinero y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Vale la pena cobrar! Pide dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Vale la pena cobrar! Pide dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY]: {
buttonText1: 'Envía dinero, ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
header: `Envía dinero y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `¡Hay que enviar dinero para ganar dinero! Envía dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
+ body: `¡Hay que enviar dinero para ganar dinero! Envía dinero a una cuenta nueva de Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierten en clientes de Expensify.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
buttonText1: 'Invita a un amigo y ',
buttonText2: `recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Invita a un amigo y recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- body1: `Envía tu enlace de invitación de Expensify a un amigo o a cualquier otra persona que conozcas que dedique demasiado tiempo a los gastos. Cuando comiencen una suscripción anual, obtendrás $${CONST.REFERRAL_PROGRAM.REVENUE}.`,
+ header: `Invita a un amigo y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Sé el primero en invitar a un amigo (o a cualquier otra persona) a Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierte en cliente de Expensify. Comparte tu enlace de invitación por SMS, email o publícalo en las redes sociales.`,
},
[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE]: {
buttonText1: `Recibe $${CONST.REFERRAL_PROGRAM.REVENUE}`,
- header: `Recibe $${CONST.REFERRAL_PROGRAM.REVENUE} por cada recomendación`,
- body1: 'Si conoces a alguien que dedique demasiado tiempo a los gastos (literalmente cualquiera: tu vecino, tu jefe, tu amigo de contabilidad), envíale tu enlace de invitación de Expensify:',
- body2: `Cuando comiencen una suscripción anual, obtendrás $${CONST.REFERRAL_PROGRAM.REVENUE}. Así de fácil.`,
+ header: `Invita a un amigo y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE}`,
+ body: `Sé el primero en invitar a un amigo (o a cualquier otra persona) a Expensify y obtiene $${CONST.REFERRAL_PROGRAM.REVENUE} si se convierte en cliente de Expensify. Comparte tu enlace de invitación por SMS, email o publícalo en las redes sociales.`,
},
copyReferralLink: 'Copiar enlace de invitación',
},
diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts
index b0d426c9774a..9b2bd2616e8e 100644
--- a/src/libs/CardUtils.ts
+++ b/src/libs/CardUtils.ts
@@ -107,4 +107,23 @@ function findPhysicalCard(cards: Card[]) {
return cards.find((card) => !card.isVirtual);
}
-export {isExpensifyCard, isCorporateCard, getDomainCards, getMonthFromExpirationDateString, getYearFromExpirationDateString, maskCard, getCardDescription, findPhysicalCard};
+/**
+ * Checks if any of the cards in the list have detected fraud
+ *
+ * @param cardList - collection of assigned cards
+ */
+function hasDetectedFraud(cardList: Record): boolean {
+ return Object.values(cardList).some((card) => card.fraud !== CONST.EXPENSIFY_CARD.FRAUD_TYPES.NONE);
+}
+
+export {
+ isExpensifyCard,
+ isCorporateCard,
+ getDomainCards,
+ getMonthFromExpirationDateString,
+ getYearFromExpirationDateString,
+ maskCard,
+ getCardDescription,
+ findPhysicalCard,
+ hasDetectedFraud,
+};
diff --git a/src/libs/ComposerUtils/updateNumberOfLines/types.ts b/src/libs/ComposerUtils/updateNumberOfLines/types.ts
index 5e109afe8959..c121eaaef319 100644
--- a/src/libs/ComposerUtils/updateNumberOfLines/types.ts
+++ b/src/libs/ComposerUtils/updateNumberOfLines/types.ts
@@ -1,6 +1,6 @@
import {NativeSyntheticEvent, TextInputContentSizeChangeEventData} from 'react-native';
import ComposerProps from '@libs/ComposerUtils/types';
-import {type ThemeStyles} from '@styles/styles';
+import {type ThemeStyles} from '@styles/index';
type UpdateNumberOfLines = (props: ComposerProps, event: NativeSyntheticEvent, styles: ThemeStyles) => void;
diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 153f05f4fd22..16978787806e 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -1,16 +1,22 @@
import {
addDays,
+ addHours,
+ addMinutes,
eachDayOfInterval,
eachMonthOfInterval,
endOfDay,
endOfWeek,
format,
formatDistanceToNow,
+ getDayOfYear,
isAfter,
isBefore,
isSameDay,
+ isSameSecond,
isSameYear,
isValid,
+ parse,
+ set,
setDefaultOptions,
startOfWeek,
subDays,
@@ -28,6 +34,8 @@ import {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails';
import * as CurrentDate from './actions/CurrentDate';
import * as Localize from './Localize';
+type CustomStatusTypes = (typeof CONST.CUSTOM_STATUS_TYPES)[keyof typeof CONST.CUSTOM_STATUS_TYPES];
+type TimePeriod = 'AM' | 'PM';
type Locale = ValueOf;
let currentUserAccountID: number | undefined;
@@ -341,6 +349,115 @@ function getDateStringFromISOTimestamp(isoTimestamp: string): string {
return dateString;
}
+/**
+ * returns {string} example: 2023-05-16 05:34:14
+ */
+function getThirtyMinutesFromNow(): string {
+ const date = addMinutes(new Date(), 30);
+ return format(date, 'yyyy-MM-dd HH:mm:ss');
+}
+
+/**
+ * returns {string} example: 2023-05-16 05:34:14
+ */
+function getOneHourFromNow(): string {
+ const date = addHours(new Date(), 1);
+ return format(date, 'yyyy-MM-dd HH:mm:ss');
+}
+
+/**
+ * returns {string} example: 2023-05-16 05:34:14
+ */
+function getEndOfToday(): string {
+ const date = endOfDay(new Date());
+ return format(date, 'yyyy-MM-dd HH:mm:ss');
+}
+
+/**
+ * returns {string} example: 2023-05-16 05:34:14
+ */
+function getOneWeekFromNow(): string {
+ const date = addDays(new Date(), 7);
+ return format(date, 'yyyy-MM-dd HH:mm:ss');
+}
+
+/**
+ * param {string} dateTimeString
+ * returns {string} example: 2023-05-16
+ */
+function extractDate(dateTimeString: string): string {
+ if (!dateTimeString) {
+ return '';
+ }
+ if (dateTimeString === 'never') {
+ return '';
+ }
+ const date = new Date(dateTimeString);
+ return format(date, 'yyyy-MM-dd');
+}
+
+/**
+ * param {string} dateTimeString
+ * returns {string} example: 11:10 PM
+ */
+function extractTime12Hour(dateTimeString: string): string {
+ if (!dateTimeString || dateTimeString === 'never') {
+ return '';
+ }
+ const date = new Date(dateTimeString);
+ return format(date, 'hh:mm a');
+}
+
+/**
+ * param {string} dateTimeString
+ * returns {string} example: 2023-05-16 11:10 PM
+ */
+function formatDateTimeTo12Hour(dateTimeString: string): string {
+ if (!dateTimeString) {
+ return '';
+ }
+ const date = new Date(dateTimeString);
+ return format(date, 'yyyy-MM-dd hh:mm a');
+}
+
+/**
+ * param {string} type - one of the values from CONST.CUSTOM_STATUS_TYPES
+ * returns {string} example: 2023-05-16 11:10:00 or ''
+ */
+function getDateFromStatusType(type: CustomStatusTypes): string {
+ switch (type) {
+ case CONST.CUSTOM_STATUS_TYPES.THIRTY_MINUTES:
+ return getThirtyMinutesFromNow();
+ case CONST.CUSTOM_STATUS_TYPES.ONE_HOUR:
+ return getOneHourFromNow();
+ case CONST.CUSTOM_STATUS_TYPES.AFTER_TODAY:
+ return getEndOfToday();
+ case CONST.CUSTOM_STATUS_TYPES.AFTER_WEEK:
+ return getOneWeekFromNow();
+ case CONST.CUSTOM_STATUS_TYPES.NEVER:
+ return CONST.CUSTOM_STATUS_TYPES.NEVER;
+ default:
+ return '';
+ }
+}
+
+/**
+ * param {string} data - either a value from CONST.CUSTOM_STATUS_TYPES or a dateTime string in the format YYYY-MM-DD HH:mm
+ * returns {string} example: 2023-05-16 11:10 PM or 'Today'
+ */
+function getLocalizedTimePeriodDescription(data: string): string {
+ const {translateLocal} = Localize;
+ switch (data) {
+ case getEndOfToday():
+ return translateLocal('statusPage.timePeriods.afterToday');
+ case CONST.CUSTOM_STATUS_TYPES.NEVER:
+ case '':
+ return translateLocal('statusPage.timePeriods.never');
+ default:
+ return formatDateTimeTo12Hour(data);
+ }
+}
+
/**
* receive date like 2020-05-16 05:34:14 and format it to show in string like "Until 05:34 PM"
*/
@@ -374,10 +491,172 @@ function getStatusUntilDate(inputDate: string): string {
}
/**
+ * Update the time for a given date.
+ *
+ * param {string} updatedTime - Time in "hh:mm A" or "HH:mm:ss" or "yyyy-MM-dd HH:mm:ss" format.
+ * param {string} inputDateTime - Date in "YYYY-MM-DD HH:mm:ss" or "YYYY-MM-DD" format.
+ * returns {string} - Date with updated time in "YYYY-MM-DD HH:mm:ss" format.
+ */
+const combineDateAndTime = (updatedTime: string, inputDateTime: string): string => {
+ if (!updatedTime || !inputDateTime) {
+ return '';
+ }
+
+ let parsedTime: Date | null = null;
+ if (updatedTime.includes('-')) {
+ // it's in "yyyy-MM-dd HH:mm:ss" format
+ const tempTime = parse(updatedTime, 'yyyy-MM-dd HH:mm:ss', new Date());
+ if (isValid(tempTime)) {
+ parsedTime = tempTime;
+ }
+ } else if (updatedTime.includes(':')) {
+ // it's in "hh:mm a" format
+ const tempTime = parse(updatedTime, 'hh:mm a', new Date());
+ if (isValid(tempTime)) {
+ parsedTime = tempTime;
+ }
+ }
+
+ if (!parsedTime) {
+ return '';
+ }
+
+ let parsedDateTime: Date | null = null;
+ if (inputDateTime.includes(':')) {
+ // Check if it includes time
+ const tempDateTime = parse(inputDateTime, 'yyyy-MM-dd HH:mm:ss', new Date());
+ if (isValid(tempDateTime)) {
+ parsedDateTime = tempDateTime;
+ }
+ } else {
+ const tempDateTime = parse(inputDateTime, 'yyyy-MM-dd', new Date());
+ if (isValid(tempDateTime)) {
+ parsedDateTime = tempDateTime;
+ }
+ }
+
+ if (!parsedDateTime) {
+ return '';
+ }
+
+ const updatedDateTime = set(parsedDateTime, {
+ hours: parsedTime.getHours(),
+ minutes: parsedTime.getMinutes(),
+ seconds: parsedTime.getSeconds(),
+ });
+
+ return format(updatedDateTime, 'yyyy-MM-dd HH:mm:ss');
+};
+
+/**
+ * param {String} dateTime in 'HH:mm:ss' format
+ * returns {Object}
+ * example {hour: '11', minute: '10', period: 'AM'}
+ */
+function get12HourTimeObjectFromDate(dateTime: string): {hour: string; minute: string; period: string} {
+ if (!dateTime) {
+ return {
+ hour: '12',
+ minute: '00',
+ period: 'PM',
+ };
+ }
+ const parsedTime = parse(dateTime, 'hh:mm a', new Date());
+ return {
+ hour: format(parsedTime, 'hh'),
+ minute: format(parsedTime, 'mm'),
+ period: format(parsedTime, 'a').toUpperCase(),
+ };
+}
+
+/**
+ * param {String} timeString
+ * returns {String}
+ * example getTimePeriod('11:10 PM') // 'PM'
+ */
+function getTimePeriod(timeString: string): TimePeriod {
+ const parts = timeString.split(' ');
+ return parts[1] as TimePeriod;
+}
+
+/**
+ * param {String} dateTimeStringFirst // YYYY-MM-DD HH:mm:ss
+ * param {String} dateTimeStringSecond // YYYY-MM-DD HH:mm:ss
+ * returns {Boolean}
+ */
+function areDatesIdentical(dateTimeStringFirst: string, dateTimeStringSecond: string): boolean {
+ const date1 = parse(dateTimeStringFirst, 'yyyy-MM-dd HH:mm:ss', new Date());
+ const date2 = parse(dateTimeStringSecond, 'yyyy-MM-dd HH:mm:ss', new Date());
+
+ return isSameSecond(date1, date2);
+}
+
+/**
+ * Checks if the time input is at least one minute in the future.
+ * param {String} timeString: '04:24 AM'
+ * param {String} dateTimeString: '2023-11-14 14:24:00'
+ * returns {Boolean}
+ */
+const isTimeAtLeastOneMinuteInFuture = ({timeString, dateTimeString}: {timeString?: string; dateTimeString: string}): boolean => {
+ let dateToCheck = dateTimeString;
+ if (timeString) {
+ // return false;
+ // Parse the hour and minute from the time input
+ const [hourStr] = timeString.split(/[:\s]+/);
+ const hour = parseInt(hourStr, 10);
+
+ if (hour === 0) {
+ return false;
+ }
+
+ dateToCheck = combineDateAndTime(timeString, dateTimeString);
+ }
+
+ // Get current date and time
+ const now = new Date();
+
+ // Check if the combinedDate is at least one minute later than the current date and time
+ return isAfter(new Date(dateToCheck), addMinutes(now, 1));
+};
+
+/**
+ * Checks if the input date is in the future compared to the reference date.
+ * param {Date} inputDate - The date to validate.
+ * param {Date} referenceDate - The date to compare against.
+ * returns {string} - Returns an error key if validation fails, otherwise an empty string.
+ */
+const getDayValidationErrorKey = (inputDate: Date): string => {
+ if (!inputDate) {
+ return '';
+ }
+ const currentYear = getDayOfYear(new Date());
+ const inputYear = getDayOfYear(inputDate);
+ if (inputYear < currentYear) {
+ return 'common.error.invalidDateShouldBeFuture';
+ }
+ return '';
+};
+
+/**
+ * Checks if the input time is at least one minute in the future compared to the reference time.
+ * param {Date} inputTime - The time to validate.
+ * param {Date} referenceTime - The time to compare against.
+ * returns {string} - Returns an error key if validation fails, otherwise an empty string.
+ */
+const getTimeValidationErrorKey = (inputTime: Date): string => {
+ const timeNowPlusOneMinute = addMinutes(new Date(), 1);
+ if (isBefore(inputTime, timeNowPlusOneMinute)) {
+ return 'common.error.invalidTimeShouldBeFuture';
+ }
+ return '';
+};
+
+/**
+ *
* Get a date and format this date using the UTC timezone.
- * @param datetime
- * @param dateFormat
- * @returns If the date is valid, returns the formatted date with the UTC timezone, otherwise returns an empty string.
+ * param datetime
+ * param dateFormat
+ * returns If the date is valid, returns the formatted date with the UTC timezone, otherwise returns an empty string.
*/
function formatWithUTCTimeZone(datetime: string, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING) {
const date = new Date(datetime);
@@ -406,13 +685,29 @@ const DateUtils = {
setLocale,
subtractMillisecondsFromDateTime,
getDateStringFromISOTimestamp,
+ getThirtyMinutesFromNow,
+ getEndOfToday,
+ getOneWeekFromNow,
+ getDateFromStatusType,
+ getOneHourFromNow,
+ extractDate,
+ formatDateTimeTo12Hour,
getStatusUntilDate,
+ extractTime12Hour,
+ get12HourTimeObjectFromDate,
+ areDatesIdentical,
+ getTimePeriod,
+ getLocalizedTimePeriodDescription,
+ combineDateAndTime,
+ getDayValidationErrorKey,
+ getTimeValidationErrorKey,
isToday,
isTomorrow,
isYesterday,
getMonthNames,
getDaysOfWeek,
formatWithUTCTimeZone,
+ isTimeAtLeastOneMinuteInFuture,
};
export default DateUtils;
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
index 5e8a9f502dc5..f6572c84709d 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
@@ -1,6 +1,7 @@
import React, {memo, useEffect, useRef} from 'react';
import {View} from 'react-native';
import Onyx, {OnyxEntry, withOnyx} from 'react-native-onyx';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import KeyboardShortcut from '@libs/KeyboardShortcut';
import getCurrentUrl from '@libs/Navigation/currentUrl';
@@ -14,7 +15,6 @@ import DemoSetupPage from '@pages/DemoSetupPage';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import DesktopSignInRedirectPage from '@pages/signin/DesktopSignInRedirectPage';
import SearchInputManager from '@pages/workspace/SearchInputManager';
-import useThemeStyles from '@styles/useThemeStyles';
import * as App from '@userActions/App';
import * as Download from '@userActions/Download';
import * as Modal from '@userActions/Modal';
@@ -147,7 +147,7 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom
const chatShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_CHAT;
const currentUrl = getCurrentUrl();
const isLoggingInAsNewUser = !!session?.email && SessionUtils.isLoggingInAsNewUser(currentUrl, session.email);
- const shouldGetAllData = !!isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession() || isLoggingInAsNewUser;
+ const shouldGetAllData = !!isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession();
// Sign out the current user if we're transitioning with a different user
const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS);
if (isLoggingInAsNewUser && isTransitioning) {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
index 29449f52ecd6..256ea6d4eceb 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx
@@ -1,6 +1,7 @@
import {ParamListBase} from '@react-navigation/routers';
import {CardStyleInterpolators, createStackNavigator, StackNavigationOptions} from '@react-navigation/stack';
import React, {useMemo} from 'react';
+import useThemeStyles from '@hooks/useThemeStyles';
import type {
AddPersonalBankAccountNavigatorParamList,
DetailsNavigatorParamList,
@@ -28,7 +29,6 @@ import type {
TeachersUniteNavigatorParamList,
WalletStatementNavigatorParamList,
} from '@navigation/types';
-import useThemeStyles from '@styles/useThemeStyles';
import SCREENS from '@src/SCREENS';
import type {Screen} from '@src/SCREENS';
@@ -197,8 +197,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/settings/Preferences/PreferencesPage').default as React.ComponentType,
[SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE]: () => require('../../../pages/settings/Preferences/PriorityModePage').default as React.ComponentType,
[SCREENS.SETTINGS.PREFERENCES.LANGUAGE]: () => require('../../../pages/settings/Preferences/LanguagePage').default as React.ComponentType,
- // Will be uncommented as part of https://github.com/Expensify/App/issues/21670
- // [SCREENS.SETTINGS.PREFERENCES.THEME]: () => require('../../../pages/settings/Preferences/ThemePage').default as React.ComponentType,
+ [SCREENS.SETTINGS.PREFERENCES.THEME]: () => require('../../../pages/settings/Preferences/ThemePage').default as React.ComponentType,
[SCREENS.SETTINGS.CLOSE]: () => require('../../../pages/settings/Security/CloseAccountPage').default as React.ComponentType,
[SCREENS.SETTINGS.SECURITY]: () => require('../../../pages/settings/Security/SecuritySettingsPage').default as React.ComponentType,
[SCREENS.SETTINGS.ABOUT]: () => require('../../../pages/settings/AboutPage/AboutPage').default as React.ComponentType,
@@ -219,7 +218,9 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType,
[SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType,
[SCREENS.SETTINGS.PROFILE.STATUS]: () => require('../../../pages/settings/Profile/CustomStatus/StatusPage').default as React.ComponentType,
- [SCREENS.SETTINGS.PROFILE.STATUS_SET]: () => require('../../../pages/settings/Profile/CustomStatus/StatusSetPage').default as React.ComponentType,
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER]: () => require('../../../pages/settings/Profile/CustomStatus/StatusClearAfterPage').default as React.ComponentType,
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_DATE]: () => require('../../../pages/settings/Profile/CustomStatus/SetDatePage').default as React.ComponentType,
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_TIME]: () => require('../../../pages/settings/Profile/CustomStatus/SetTimePage').default as React.ComponentType,
[SCREENS.WORKSPACE.INITIAL]: () => require('../../../pages/workspace/WorkspaceInitialPage').default as React.ComponentType,
[SCREENS.WORKSPACE.SETTINGS]: () => require('../../../pages/workspace/WorkspaceSettingsPage').default as React.ComponentType,
[SCREENS.WORKSPACE.CURRENCY]: () => require('../../../pages/workspace/WorkspaceSettingsCurrencyPage').default as React.ComponentType,
diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx
index 228ea6bd3dce..f2cdd140f7d8 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx
@@ -1,9 +1,9 @@
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
+import useThemeStyles from '@hooks/useThemeStyles';
import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import type {CentralPaneNavigatorParamList} from '@navigation/types';
-import useThemeStyles from '@styles/useThemeStyles';
import SCREENS from '@src/SCREENS';
const Stack = createStackNavigator();
diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
index 31eb818b60dc..065de8da578b 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import {Animated, View} from 'react-native';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
type OverlayProps = {
@@ -27,14 +27,14 @@ function Overlay({onPress}: OverlayProps) {
style={styles.draggableTopBar}
onPress={onPress}
accessibilityLabel={translate('common.close')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
nativeID={CONST.OVERLAY.TOP_BUTTON_NATIVE_ID}
/>
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
index 10b8129bc3e7..bd790589c8d1 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
@@ -2,11 +2,11 @@ import {createStackNavigator, StackScreenProps} from '@react-navigation/stack';
import React, {useMemo} from 'react';
import {View} from 'react-native';
import NoDropZone from '@components/DragAndDrop/NoDropZone';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators';
import RHPScreenOptions from '@libs/Navigation/AppNavigator/RHPScreenOptions';
import type {AuthScreensParamList, RightModalNavigatorParamList} from '@navigation/types';
-import useThemeStyles from '@styles/useThemeStyles';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
import Overlay from './Overlay';
diff --git a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts
index 6cae31a219f9..814c61ad32a3 100644
--- a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts
+++ b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts
@@ -1,5 +1,5 @@
import {CardStyleInterpolators, StackNavigationOptions} from '@react-navigation/stack';
-import {ThemeStyles} from '@styles/styles';
+import {ThemeStyles} from '@styles/index';
/**
* RHP stack navigator screen options generator function
diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
index b294e6d7ab11..379c5281b78f 100644
--- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
+++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts
@@ -1,6 +1,6 @@
import {StackCardInterpolationProps, StackNavigationOptions} from '@react-navigation/stack';
-import getNavigationModalCardStyle from '@styles/getNavigationModalCardStyles';
-import {ThemeStyles} from '@styles/styles';
+import {ThemeStyles} from '@styles/index';
+import getNavigationModalCardStyle from '@styles/utils/getNavigationModalCardStyles';
import variables from '@styles/variables';
import CONFIG from '@src/CONFIG';
import modalCardStyleInterpolator from './modalCardStyleInterpolator';
diff --git a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
index f7e772148e79..eff88422cc5c 100644
--- a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
+++ b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts
@@ -1,6 +1,6 @@
import type {StackCardInterpolatedStyle, StackCardInterpolationProps} from '@react-navigation/stack';
import {Animated} from 'react-native';
-import getCardStyles from '@styles/cardStyles';
+import getCardStyles from '@styles/utils/cardStyles';
import variables from '@styles/variables';
export default (isSmallScreenWidth: boolean, isFullScreenModal: boolean, {current: {progress}, inverted, layouts: {screen}}: StackCardInterpolationProps): StackCardInterpolatedStyle => {
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 7c0b9ef4fc8c..48523162ba2e 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -2,9 +2,9 @@ import {DefaultTheme, getPathFromState, NavigationContainer, NavigationState} fr
import React, {useEffect, useMemo, useRef} from 'react';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useFlipper from '@hooks/useFlipper';
+import useTheme from '@hooks/useTheme';
import useWindowDimensions from '@hooks/useWindowDimensions';
import Log from '@libs/Log';
-import useTheme from '@styles/themes/useTheme';
import AppNavigator from './AppNavigator';
import linkingConfig from './linkingConfig';
import Navigation, {navigationRef} from './Navigation';
diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts
index acbc7c8f1702..0383455a5946 100644
--- a/src/libs/Navigation/linkingConfig.ts
+++ b/src/libs/Navigation/linkingConfig.ts
@@ -7,7 +7,15 @@ import SCREENS from '@src/SCREENS';
import {RootStackParamList} from './types';
const linkingConfig: LinkingOptions = {
- prefixes: ['new-expensify://', 'https://www.expensify.cash', 'https://staging.expensify.cash', 'https://dev.new.expensify.com', CONST.NEW_EXPENSIFY_URL, CONST.STAGING_NEW_EXPENSIFY_URL],
+ prefixes: [
+ 'app://-/',
+ 'new-expensify://',
+ 'https://www.expensify.cash',
+ 'https://staging.expensify.cash',
+ 'https://dev.new.expensify.com',
+ CONST.NEW_EXPENSIFY_URL,
+ CONST.STAGING_NEW_EXPENSIFY_URL,
+ ],
config: {
initialRouteName: SCREENS.HOME,
screens: {
@@ -206,9 +214,14 @@ const linkingConfig: LinkingOptions = {
path: ROUTES.SETTINGS_STATUS,
exact: true,
},
- [SCREENS.SETTINGS.PROFILE.STATUS_SET]: {
- path: ROUTES.SETTINGS_STATUS_SET,
- exact: true,
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER]: {
+ path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER,
+ },
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_DATE]: {
+ path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER_DATE,
+ },
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_TIME]: {
+ path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER_TIME,
},
[SCREENS.WORKSPACE.INITIAL]: {
path: ROUTES.WORKSPACE_INITIAL.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index b69552f6fe0f..94a07ddc6b73 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -82,7 +82,9 @@ type SettingsNavigatorParamList = {
[SCREENS.SETTINGS.ADD_DEBIT_CARD]: undefined;
[SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: undefined;
[SCREENS.SETTINGS.PROFILE.STATUS]: undefined;
- [SCREENS.SETTINGS.PROFILE.STATUS_SET]: undefined;
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER]: undefined;
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_DATE]: undefined;
+ [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_TIME]: undefined;
[SCREENS.WORKSPACE.INITIAL]: undefined;
[SCREENS.WORKSPACE.SETTINGS]: undefined;
[SCREENS.WORKSPACE.CURRENCY]: undefined;
diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index ac5c999d5388..b58f2af1eeac 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -15,9 +15,9 @@ function parseMessage(messages: Message[] | undefined) {
});
const formattedHtml = nextStepHTML
- .replace(/%expenses/g, 'this expense')
- .replace(/%Expenses/g, 'This expense')
- .replace(/%tobe/g, 'is');
+ .replace(/%expenses/g, 'these expenses')
+ .replace(/%Expenses/g, 'These expenses')
+ .replace(/%tobe/g, 'are');
return `${formattedHtml}`;
}
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 95a8c52649d3..4da344c3608b 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -390,14 +390,14 @@ function getLastMessageTextForReport(report) {
lastMessageTextFromReport = ReportUtils.formatReportLastMessageText(properSchemaForMoneyRequestMessage);
} else if (ReportActionUtils.isReportPreviewAction(lastReportAction)) {
const iouReport = ReportUtils.getReport(ReportActionUtils.getIOUReportIDFromReportActionPreview(lastReportAction));
- const lastIOUMoneyReport = _.find(
+ const lastIOUMoneyReportAction = _.find(
allSortedReportActions[iouReport.reportID],
(reportAction, key) =>
ReportActionUtils.shouldReportActionBeVisible(reportAction, key) &&
reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE &&
ReportActionUtils.isMoneyRequestAction(reportAction),
);
- lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastIOUMoneyReport, true, ReportUtils.isChatReport(report));
+ lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastIOUMoneyReportAction, true, ReportUtils.isChatReport(report));
} else if (ReportActionUtils.isReimbursementQueuedAction(lastReportAction)) {
lastMessageTextFromReport = ReportUtils.getReimbursementQueuedActionMessage(lastReportAction, report);
} else if (ReportActionUtils.isReimbursementDeQueuedAction(lastReportAction)) {
diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts
index ee7a293f6ad1..e41b3295a2c5 100644
--- a/src/libs/PaymentUtils.ts
+++ b/src/libs/PaymentUtils.ts
@@ -1,5 +1,5 @@
import getBankIcon from '@components/Icon/BankIcons';
-import {type ThemeStyles} from '@styles/styles';
+import {type ThemeStyles} from '@styles/index';
import CONST from '@src/CONST';
import BankAccount from '@src/types/onyx/BankAccount';
import Fund from '@src/types/onyx/Fund';
diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts
index 43e7ef9fbbc8..9cde613ebb5a 100644
--- a/src/libs/Permissions.ts
+++ b/src/libs/Permissions.ts
@@ -18,6 +18,10 @@ function canUseCommentLinking(betas: OnyxEntry): boolean {
return !!betas?.includes(CONST.BETAS.BETA_COMMENT_LINKING) || canUseAllBetas(betas);
}
+function canUseReportFields(betas: OnyxEntry): boolean {
+ return !!betas?.includes(CONST.BETAS.REPORT_FIELDS) || canUseAllBetas(betas);
+}
+
/**
* We're requiring you to be added to the policy rooms beta on dev,
* since contributors have been reporting a number of false issues related to the feature being under development.
@@ -45,4 +49,5 @@ export default {
canUsePolicyRooms,
canUseLinkPreviews,
canUseViolations,
+ canUseReportFields,
};
diff --git a/src/styles/PopoverWithMeasuredContentStyleUtils.ts b/src/libs/PopoverWithMeasuredContentUtils.ts
similarity index 88%
rename from src/styles/PopoverWithMeasuredContentStyleUtils.ts
rename to src/libs/PopoverWithMeasuredContentUtils.ts
index 94a0fb77d8bb..b932249211be 100644
--- a/src/styles/PopoverWithMeasuredContentStyleUtils.ts
+++ b/src/libs/PopoverWithMeasuredContentUtils.ts
@@ -1,5 +1,5 @@
-import roundToNearestMultipleOfFour from './utils/roundToNearestMultipleOfFour';
-import variables from './variables';
+import roundToNearestMultipleOfFour from '@styles/utils/roundToNearestMultipleOfFour';
+import variables from '@styles/variables';
/**
* Compute the amount that the Context menu's Anchor needs to be horizontally shifted
@@ -50,6 +50,6 @@ function computeVerticalShift(anchorTopEdge: number, menuHeight: number, windowH
return 0;
}
-const PopoverWithMeasuredContentStyleUtils = {computeHorizontalShift, computeVerticalShift};
+const PopoverWithMeasuredContentUtils = {computeHorizontalShift, computeVerticalShift};
-export default PopoverWithMeasuredContentStyleUtils;
+export default PopoverWithMeasuredContentUtils;
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 21c382346e57..9a3099ba6c02 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -375,7 +375,7 @@ function shouldReportActionBeVisible(reportAction: OnyxEntry, key:
// All other actions are displayed except thread parents, deleted, or non-pending actions
const isDeleted = isDeletedAction(reportAction);
- const isPending = !!reportAction.pendingAction;
+ const isPending = !!reportAction.pendingAction && !(!isNetworkOffline && reportAction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
return !isDeleted || isPending || isDeletedParentAction(reportAction) || isReversedTransaction(reportAction);
}
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 608bcab053f4..8729bb1bf957 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -1211,7 +1211,8 @@ function getDefaultWorkspaceAvatar(workspaceName?: string): React.FC {
function getWorkspaceAvatar(report: OnyxEntry): UserUtils.AvatarSource {
const workspaceName = getPolicyName(report, false, allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]);
- return allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]?.avatar ?? getDefaultWorkspaceAvatar(workspaceName);
+ const avatar = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]?.avatar ?? '';
+ return !isEmpty(avatar) ? avatar : getDefaultWorkspaceAvatar(workspaceName);
}
/**
@@ -3677,8 +3678,8 @@ function getRouteFromLink(url: string | null): string {
// Get the reportID from URL
let route = url;
+ const localWebAndroidRegEx = /^(https:\/\/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}))/;
linkingConfig.prefixes.forEach((prefix) => {
- const localWebAndroidRegEx = /^(http:\/\/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}))/;
if (route.startsWith(prefix)) {
route = route.replace(prefix, '');
} else if (localWebAndroidRegEx.test(route)) {
diff --git a/src/libs/SessionUtils.ts b/src/libs/SessionUtils.ts
index 6cd20e0b56b2..1afa3a75e081 100644
--- a/src/libs/SessionUtils.ts
+++ b/src/libs/SessionUtils.ts
@@ -45,7 +45,7 @@ Onyx.connect({
});
function resetDidUserLogInDuringSession() {
- loggedInDuringSession = undefined;
+ loggedInDuringSession = true;
}
function didUserLogInDuringSession() {
diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts
index 388020bc0d6d..ba977312fcfb 100644
--- a/src/libs/ValidationUtils.ts
+++ b/src/libs/ValidationUtils.ts
@@ -1,5 +1,5 @@
import {parsePhoneNumber} from 'awesome-phonenumber';
-import {addYears, endOfMonth, format, isAfter, isBefore, isSameDay, isValid, isWithinInterval, parse, startOfDay, subYears} from 'date-fns';
+import {addYears, endOfMonth, format, isAfter, isBefore, isSameDay, isValid, isWithinInterval, parse, parseISO, startOfDay, subYears} from 'date-fns';
import {URL_REGEX_WITH_REQUIRED_PROTOCOL} from 'expensify-common/lib/Url';
import isDate from 'lodash/isDate';
import isEmpty from 'lodash/isEmpty';
@@ -8,6 +8,7 @@ import CONST from '@src/CONST';
import {Report} from '@src/types/onyx';
import * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import * as CardUtils from './CardUtils';
+import DateUtils from './DateUtils';
import * as LoginUtils from './LoginUtils';
import StringUtils from './StringUtils';
@@ -195,6 +196,28 @@ function getAgeRequirementError(date: string, minimumAge: number, maximumAge: nu
return ['privatePersonalDetails.error.dateShouldBeAfter', {dateString: format(minimalDate, CONST.DATE.FNS_FORMAT_STRING)}];
}
+/**
+ * Validate that given date is not in the past.
+ */
+function getDatePassedError(inputDate: string): string {
+ const currentDate = new Date();
+ const parsedDate = new Date(`${inputDate}T00:00:00`); // set time to 00:00:00 for accurate comparison
+
+ // If input date is not valid, return an error
+ if (!isValid(parsedDate)) {
+ return 'common.error.dateInvalid';
+ }
+
+ // Clear time for currentDate so comparison is based solely on the date
+ currentDate.setHours(0, 0, 0, 0);
+
+ if (parsedDate < currentDate) {
+ return 'common.error.dateInvalid';
+ }
+
+ return '';
+}
+
/**
* Similar to backend, checks whether a website has a valid URL or not.
* http/https/ftp URL scheme required.
@@ -361,6 +384,27 @@ function isValidAccountRoute(accountID: number): boolean {
return CONST.REGEX.NUMBER.test(String(accountID)) && accountID > 0;
}
+/**
+ * Validates that the date and time are at least one minute in the future.
+ * data - A date and time string in 'YYYY-MM-DD HH:mm:ss.sssZ' format
+ * returns an object containing the error messages for the date and time
+ */
+const validateDateTimeIsAtLeastOneMinuteInFuture = (data: string): {dateValidationErrorKey: string; timeValidationErrorKey: string} => {
+ if (!data) {
+ return {
+ dateValidationErrorKey: '',
+ timeValidationErrorKey: '',
+ };
+ }
+ const parsedInputData = parseISO(data);
+
+ const dateValidationErrorKey = DateUtils.getDayValidationErrorKey(parsedInputData);
+ const timeValidationErrorKey = DateUtils.getTimeValidationErrorKey(parsedInputData);
+ return {
+ dateValidationErrorKey,
+ timeValidationErrorKey,
+ };
+};
type ValuesType = Record;
/**
@@ -412,7 +456,9 @@ export {
doesContainReservedWord,
isNumeric,
isValidAccountRoute,
+ getDatePassedError,
isValidRecoveryCode,
+ validateDateTimeIsAtLeastOneMinuteInFuture,
prepareValues,
isValidPersonName,
};
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index 0eda0cce6b54..7513989d08c4 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -61,6 +61,15 @@ Onyx.connect({
},
});
+let allTransactionDrafts = {};
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
+ waitForCollectionCallback: true,
+ callback: (val) => {
+ allTransactionDrafts = val || {};
+ },
+});
+
let allTransactionViolations;
Onyx.connect({
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
@@ -661,11 +670,12 @@ function getMoneyRequestInformation(
// data. This is a big can of worms to change it to `Onyx.merge()` as explored in https://expensify.slack.com/archives/C05DWUDHVK7/p1692139468252109.
// I want to clean this up at some point, but it's possible this will live in the code for a while so I've created https://github.com/Expensify/App/issues/25417
// to remind me to do this.
- const existingTransaction = existingTransactionID && TransactionUtils.getTransaction(existingTransactionID);
- if (existingTransaction) {
+ const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`];
+ if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) {
optimisticTransaction = {
...optimisticTransaction,
...existingTransaction,
+ transactionID: optimisticTransaction.transactionID,
};
}
@@ -817,18 +827,17 @@ function createDistanceRequest(report, participant, comment, created, category,
}
/**
- * Edits an existing distance request
- *
* @param {String} transactionID
* @param {Number} transactionThreadReportID
* @param {Object} transactionChanges
- * @param {String} [transactionChanges.created]
- * @param {Number} [transactionChanges.amount]
- * @param {Object} [transactionChanges.comment]
- * @param {Object} [transactionChanges.waypoints]
- *
+ * @param {String} [transactionChanges.created] Present when updated the date field
+ * @param {Boolean} onlyIncludeChangedFields
+ * When 'true', then the returned params will only include the transaction details for the fields that were changed.
+ * When `false`, then the returned params will include all the transaction details, regardless of which fields were changed.
+ * This setting is necessary while the UpdateDistanceRequest API is refactored to be fully 1:1:1 in https://github.com/Expensify/App/issues/28358
+ * @returns {object}
*/
-function editDistanceMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) {
+function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, onlyIncludeChangedFields) {
const optimisticData = [];
const successData = [];
const failureData = [];
@@ -848,11 +857,15 @@ function editDistanceMoneyRequest(transactionID, transactionThreadReportID, tran
const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport);
const transactionDetails = ReportUtils.getTransactionDetails(updatedTransaction);
+ // This needs to be a JSON string since we're sending this to the MapBox API
+ transactionDetails.waypoints = JSON.stringify(transactionDetails.waypoints);
+
+ const dataToIncludeInParams = onlyIncludeChangedFields ? _.pick(transactionDetails, _.keys(transactionChanges)) : transactionDetails;
+
const params = {
- ...transactionDetails,
+ ...dataToIncludeInParams,
+ reportID: iouReport.reportID,
transactionID,
- // This needs to be a JSON string since we're sending this to the MapBox API
- waypoints: JSON.stringify(transactionDetails.waypoints),
};
// Step 3: Build the modified expense report actions
@@ -912,18 +925,43 @@ function editDistanceMoneyRequest(transactionID, transactionThreadReportID, tran
}
// Optimistically modify the transaction
+ const optimisticTransaction = onlyIncludeChangedFields ? _.pick(updatedTransaction, _.keys(transactionChanges)) : updatedTransaction;
optimisticData.push({
// We need to use SET method to save updated waypoint instead MERGE method to avoid wrong update of waypoints. More detail: https://github.com/Expensify/App/issues/30290#issuecomment-1778957070
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
- ...updatedTransaction,
+ ...optimisticTransaction,
pendingFields,
isLoading: _.has(transactionChanges, 'waypoints'),
errorFields: null,
},
});
+ // Update recently used categories if the category is changed
+ if (_.has(transactionChanges, 'category')) {
+ const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, transactionChanges.category);
+ if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`,
+ value: optimisticPolicyRecentlyUsedCategories,
+ });
+ }
+ }
+
+ // Update recently used categories if the tag is changed
+ if (_.has(transactionChanges, 'tag')) {
+ const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag);
+ if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
+ value: optimisticPolicyRecentlyUsedTags,
+ });
+ }
+ }
+
// Clear out the error fields and loading states on success
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
@@ -962,7 +1000,42 @@ function editDistanceMoneyRequest(transactionID, transactionThreadReportID, tran
value: iouReport,
});
- API.write('UpdateDistanceRequest', params, {optimisticData, successData, failureData});
+ return {
+ params,
+ onyxData: {optimisticData, successData, failureData},
+ };
+}
+
+/**
+ * Updates the created date of a money request
+ *
+ * @param {String} transactionID
+ * @param {Number} transactionThreadReportID
+ * @param {String} val
+ */
+function updateMoneyRequestDate(transactionID, transactionThreadReportID, val) {
+ const transactionChanges = {
+ created: val,
+ };
+ const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
+ API.write('UpdateMoneyRequestDate', params, onyxData);
+}
+
+/**
+ * Edits an existing distance request
+ *
+ * @param {String} transactionID
+ * @param {Number} transactionThreadReportID
+ * @param {Object} transactionChanges
+ * @param {String} [transactionChanges.created]
+ * @param {Number} [transactionChanges.amount]
+ * @param {Object} [transactionChanges.comment]
+ * @param {Object} [transactionChanges.waypoints]
+ *
+ */
+function updateDistanceRequest(transactionID, transactionThreadReportID, transactionChanges) {
+ const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, false);
+ API.write('UpdateDistanceRequest', params, onyxData);
}
/**
@@ -1991,8 +2064,6 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
updatedChatReport.lastMessageHtml = messageText;
}
- const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag);
-
const isScanning = TransactionUtils.hasReceipt(updatedTransaction) && TransactionUtils.isReceiptBeingScanned(updatedTransaction);
// STEP 4: Compose the optimistic data
@@ -2052,12 +2123,28 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
: []),
];
- if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
- optimisticData.push({
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
- value: optimisticPolicyRecentlyUsedTags,
- });
+ // Update recently used categories if the category is changed
+ if (_.has(transactionChanges, 'category')) {
+ const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, transactionChanges.category);
+ if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`,
+ value: optimisticPolicyRecentlyUsedCategories,
+ });
+ }
+ }
+
+ // Update recently used categories if the tag is changed
+ if (_.has(transactionChanges, 'tag')) {
+ const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag);
+ if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
+ value: optimisticPolicyRecentlyUsedTags,
+ });
+ }
}
const successData = [
@@ -2153,7 +2240,7 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
*/
function editMoneyRequest(transaction, transactionThreadReportID, transactionChanges) {
if (TransactionUtils.isDistanceRequest(transaction)) {
- editDistanceMoneyRequest(transaction.transactionID, transactionThreadReportID, transactionChanges);
+ updateDistanceRequest(transaction.transactionID, transactionThreadReportID, transactionChanges);
} else {
editRegularMoneyRequest(transaction.transactionID, transactionThreadReportID, transactionChanges);
}
@@ -3263,6 +3350,7 @@ export {
setMoneyRequestTag,
setUpDistanceTransaction,
navigateToNextPage,
+ updateMoneyRequestDate,
replaceReceipt,
detachReceipt,
getIOUReportID,
diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts
index b3d1e3e23a24..3547a3053a02 100644
--- a/src/libs/actions/PaymentMethods.ts
+++ b/src/libs/actions/PaymentMethods.ts
@@ -1,12 +1,14 @@
import {createRef} from 'react';
import Onyx, {OnyxUpdate} from 'react-native-onyx';
+import {OnyxEntry} from 'react-native-onyx/lib/types';
import {ValueOf} from 'type-fest';
import * as API from '@libs/API';
import * as CardUtils from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
-import ONYXKEYS, {OnyxValues} from '@src/ONYXKEYS';
+import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
+import type {BankAccountList, FundList} from '@src/types/onyx';
import PaymentMethod from '@src/types/onyx/PaymentMethod';
import {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer';
@@ -304,7 +306,7 @@ function dismissSuccessfulTransferBalancePage() {
* Looks through each payment method to see if there is an existing error
*
*/
-function hasPaymentMethodError(bankList: OnyxValues[typeof ONYXKEYS.BANK_ACCOUNT_LIST], fundList: OnyxValues[typeof ONYXKEYS.FUND_LIST]): boolean {
+function hasPaymentMethodError(bankList: OnyxEntry, fundList: OnyxEntry): boolean {
const combinedPaymentMethods = {...bankList, ...fundList};
return Object.values(combinedPaymentMethods).some((item) => Object.keys(item.errors ?? {}).length);
diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js
index 04f62ab0c393..f33e6637e2de 100644
--- a/src/libs/actions/Policy.js
+++ b/src/libs/actions/Policy.js
@@ -112,13 +112,6 @@ Onyx.connect({
callback: (val) => (allRecentlyUsedTags = val),
});
-let networkStatus = {};
-Onyx.connect({
- key: ONYXKEYS.NETWORK,
- waitForCollectionCallback: true,
- callback: (val) => (networkStatus = val),
-});
-
/**
* Stores in Onyx the policy ID of the last workspace that was accessed by the user
* @param {String|null} policyID
@@ -957,7 +950,7 @@ function updateWorkspaceCustomUnitAndRate(policyID, currentCustomUnit, newCustom
'UpdateWorkspaceCustomUnitAndRate',
{
policyID,
- ...(!networkStatus.isOffline && {lastModified}),
+ lastModified,
customUnit: JSON.stringify(newCustomUnitParam),
customUnitRate: JSON.stringify(newCustomUnitParam.rates),
},
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 134b78627c61..9977693896ee 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -19,6 +19,7 @@ import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import LocalNotification from '@libs/Notification/LocalNotification';
import {ReportCommentParams} from '@libs/Notification/LocalNotification/types';
+import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as Pusher from '@libs/Pusher/pusher';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
@@ -2053,29 +2054,22 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal
// If a workspace member is leaving a workspace room, they don't actually lose the room from Onyx.
// Instead, their notification preference just gets set to "hidden".
const optimisticData: OnyxUpdate[] = [
- isWorkspaceMemberLeavingWorkspaceRoom
- ? {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
- value: {
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
+ value: isWorkspaceMemberLeavingWorkspaceRoom
+ ? {
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
- },
- }
- : {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
- value: {
- reportID,
+ }
+ : {
+ reportID: null,
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
statusNum: CONST.REPORT.STATUS.CLOSED,
- chatType: report.chatType,
- parentReportID: report.parentReportID,
- parentReportActionID: report.parentReportActionID,
- policyID: report.policyID,
- type: report.type,
+ notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
- },
+ },
];
+
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
@@ -2126,11 +2120,19 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record typeof accountID === 'number',
);
+ type PersonalDetailsOnyxData = {
+ optimisticData: OnyxUpdate[];
+ successData: OnyxUpdate[];
+ failureData: OnyxUpdate[];
+ };
+
+ const logins = inviteeEmails.map((memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin));
+ const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs) as PersonalDetailsOnyxData;
+
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
@@ -2139,8 +2141,11 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record {
if (!el) {
return;
diff --git a/src/pages/EditRequestMerchantPage.js b/src/pages/EditRequestMerchantPage.js
index 53cb4946d640..5fa14d850f45 100644
--- a/src/pages/EditRequestMerchantPage.js
+++ b/src/pages/EditRequestMerchantPage.js
@@ -8,7 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -59,7 +59,7 @@ function EditRequestMerchantPage({defaultMerchant, onSubmit}) {
defaultValue={defaultMerchant}
label={translate('common.merchant')}
accessibilityLabel={translate('common.merchant')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(e) => (merchantInputRef.current = e)}
/>
diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js
index 95313bea142d..2bdf3d19f16a 100644
--- a/src/pages/EditRequestPage.js
+++ b/src/pages/EditRequestPage.js
@@ -1,7 +1,7 @@
import lodashGet from 'lodash/get';
import lodashValues from 'lodash/values';
import PropTypes from 'prop-types';
-import React, {useEffect, useMemo} from 'react';
+import React, {useCallback, useEffect, useMemo} from 'react';
import {withOnyx} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import categoryPropTypes from '@components/categoryPropTypes';
@@ -85,9 +85,6 @@ function EditRequestPage({report, route, parentReport, policyCategories, policyT
} = ReportUtils.getTransactionDetails(transaction);
const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency;
-
- // Take only the YYYY-MM-DD value
- const transactionCreated = TransactionUtils.getCreated(transaction);
const fieldToEdit = lodashGet(route, ['params', 'field'], '');
// For now, it always defaults to the first tag of the policy
@@ -123,6 +120,19 @@ function EditRequestPage({report, route, parentReport, policyCategories, policyT
Navigation.dismissModal(report.reportID);
}
+ const saveCreated = useCallback(
+ ({created: newCreated}) => {
+ // If the value hasn't changed, don't request to save changes on the server and just close the modal
+ if (newCreated === TransactionUtils.getCreated(transaction)) {
+ Navigation.dismissModal();
+ return;
+ }
+ IOU.updateMoneyRequestDate(transaction.transactionID, report.reportID, newCreated);
+ Navigation.dismissModal();
+ },
+ [transaction, report],
+ );
+
if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) {
return (
{
- // In case the date hasn't been changed, do not make the API request.
- if (transactionChanges.created === transactionCreated) {
- Navigation.dismissModal();
- return;
- }
- editMoneyRequest(transactionChanges);
- }}
+ defaultCreated={TransactionUtils.getCreated(transaction)}
+ onSubmit={saveCreated}
/>
);
}
diff --git a/src/pages/EditRequestReceiptPage.js b/src/pages/EditRequestReceiptPage.js
index 03c0aa777d5e..1525ec162963 100644
--- a/src/pages/EditRequestReceiptPage.js
+++ b/src/pages/EditRequestReceiptPage.js
@@ -5,8 +5,8 @@ import DragAndDropProvider from '@components/DragAndDrop/Provider';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import ReceiptSelector from './iou/ReceiptSelector';
const propTypes = {
diff --git a/src/pages/EditRequestTagPage.js b/src/pages/EditRequestTagPage.js
index 74cf69944f2c..8ecc4a953065 100644
--- a/src/pages/EditRequestTagPage.js
+++ b/src/pages/EditRequestTagPage.js
@@ -5,8 +5,8 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TagPicker from '@components/TagPicker';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** Transaction default tag value */
diff --git a/src/pages/EditSplitBillPage.js b/src/pages/EditSplitBillPage.js
index 3e5a5e7f5d53..dd1a96a4c8b4 100644
--- a/src/pages/EditSplitBillPage.js
+++ b/src/pages/EditSplitBillPage.js
@@ -71,10 +71,10 @@ function EditSplitBillPage({route, transaction, draftTransaction, report}) {
Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(reportID, reportActionID));
}
- function setDraftSplitTransaction(transactionChanges) {
+ const setDraftSplitTransaction = (transactionChanges) => {
IOU.setDraftSplitTransaction(transaction.transactionID, transactionChanges);
navigateBackToSplitDetails();
- }
+ };
if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) {
return (
@@ -93,13 +93,7 @@ function EditSplitBillPage({route, transaction, draftTransaction, report}) {
return (
{
- setDraftSplitTransaction({
- created: transactionChanges.created,
- });
- }}
+ onSubmit={setDraftSplitTransaction}
/>
);
}
diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js
index 6d01e601b901..f6ba2bb509fb 100644
--- a/src/pages/EnablePayments/AdditionalDetailsStep.js
+++ b/src/pages/EnablePayments/AdditionalDetailsStep.js
@@ -15,10 +15,10 @@ import TextInput from '@components/TextInput';
import TextLink from '@components/TextLink';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ValidationUtils from '@libs/ValidationUtils';
import AddressForm from '@pages/ReimbursementAccount/AddressForm';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import * as Wallet from '@userActions/Wallet';
import CONST from '@src/CONST';
@@ -193,7 +193,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys.legalFirstName)}
accessibilityLabel={translate(fieldNameTranslationKeys.legalFirstName)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={PersonalDetails.extractFirstAndLastNameFromAvailableDetails(currentUserPersonalDetails).firstName}
shouldSaveDraft
/>
@@ -203,7 +203,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys.legalLastName)}
accessibilityLabel={translate(fieldNameTranslationKeys.legalLastName)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={PersonalDetails.extractFirstAndLastNameFromAvailableDetails(currentUserPersonalDetails).lastName}
shouldSaveDraft
/>
@@ -225,7 +225,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
inputMode={CONST.INPUT_MODE.TEL}
label={translate(fieldNameTranslationKeys.phoneNumber)}
accessibilityLabel={translate(fieldNameTranslationKeys.phoneNumber)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={currentUserPersonalDetails.phoneNumber}
placeholder={translate('common.phoneNumberPlaceholder')}
shouldSaveDraft
@@ -245,7 +245,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP
containerStyles={[styles.mt4]}
label={translate(fieldNameTranslationKeys[shouldAskForFullSSN ? 'ssnFull9' : 'ssn'])}
accessibilityLabel={translate(fieldNameTranslationKeys[shouldAskForFullSSN ? 'ssnFull9' : 'ssn'])}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={shouldAskForFullSSN ? 9 : 4}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
diff --git a/src/pages/EnablePayments/FailedKYC.js b/src/pages/EnablePayments/FailedKYC.js
index de170bec4070..fc54ea9c1074 100644
--- a/src/pages/EnablePayments/FailedKYC.js
+++ b/src/pages/EnablePayments/FailedKYC.js
@@ -3,7 +3,7 @@ import {View} from 'react-native';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js
index 9e4f9d697fca..8f21d68abe4f 100644
--- a/src/pages/EnablePayments/IdologyQuestions.js
+++ b/src/pages/EnablePayments/IdologyQuestions.js
@@ -9,7 +9,7 @@ import SingleChoiceQuestion from '@components/SingleChoiceQuestion';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/EnablePayments/OnfidoPrivacy.js b/src/pages/EnablePayments/OnfidoPrivacy.js
index c542df0196cf..77b884fb2934 100644
--- a/src/pages/EnablePayments/OnfidoPrivacy.js
+++ b/src/pages/EnablePayments/OnfidoPrivacy.js
@@ -10,9 +10,9 @@ import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import ONYXKEYS from '@src/ONYXKEYS';
import walletOnfidoDataPropTypes from './walletOnfidoDataPropTypes';
diff --git a/src/pages/EnablePayments/TermsPage/LongTermsForm.js b/src/pages/EnablePayments/TermsPage/LongTermsForm.js
index 2ed7854ee6ba..d95f80e99673 100644
--- a/src/pages/EnablePayments/TermsPage/LongTermsForm.js
+++ b/src/pages/EnablePayments/TermsPage/LongTermsForm.js
@@ -6,8 +6,8 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Localize from '@libs/Localize';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const termsData = [
diff --git a/src/pages/EnablePayments/TermsPage/ShortTermsForm.js b/src/pages/EnablePayments/TermsPage/ShortTermsForm.js
index 898aec9b2c16..77f77f3cb34b 100644
--- a/src/pages/EnablePayments/TermsPage/ShortTermsForm.js
+++ b/src/pages/EnablePayments/TermsPage/ShortTermsForm.js
@@ -2,9 +2,9 @@ import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Localize from '@libs/Localize';
import userWalletPropTypes from '@pages/EnablePayments/userWalletPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.js
index 368f92f0db27..8297ca54c2b4 100644
--- a/src/pages/EnablePayments/TermsStep.js
+++ b/src/pages/EnablePayments/TermsStep.js
@@ -7,9 +7,9 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import ONYXKEYS from '@src/ONYXKEYS';
import LongTermsForm from './TermsPage/LongTermsForm';
diff --git a/src/pages/ErrorPage/ErrorBodyText/index.js b/src/pages/ErrorPage/ErrorBodyText/index.js
index d3436a2fc0a8..47b765f8f5e8 100644
--- a/src/pages/ErrorPage/ErrorBodyText/index.js
+++ b/src/pages/ErrorPage/ErrorBodyText/index.js
@@ -2,7 +2,7 @@ import React from 'react';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/ErrorPage/GenericErrorPage.js b/src/pages/ErrorPage/GenericErrorPage.js
index 01c4990cbc62..85d49a8b9074 100644
--- a/src/pages/ErrorPage/GenericErrorPage.js
+++ b/src/pages/ErrorPage/GenericErrorPage.js
@@ -9,9 +9,9 @@ import SafeAreaConsumer from '@components/SafeAreaConsumer';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/FlagCommentPage.js b/src/pages/FlagCommentPage.js
index 3695896ea473..6c6421593837 100644
--- a/src/pages/FlagCommentPage.js
+++ b/src/pages/FlagCommentPage.js
@@ -10,11 +10,11 @@ import MenuItem from '@components/MenuItem';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/GetAssistancePage.js b/src/pages/GetAssistancePage.js
index b801a91af728..a880637ca100 100644
--- a/src/pages/GetAssistancePage.js
+++ b/src/pages/GetAssistancePage.js
@@ -10,9 +10,9 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Section from '@components/Section';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
@@ -45,6 +45,7 @@ const defaultProps = {
function GetAssistancePage(props) {
const styles = useThemeStyles();
+ const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.SETTINGS_CONTACT_METHODS);
const menuItems = [
{
title: props.translate('getAssistancePage.chatWithConcierge'),
@@ -82,7 +83,7 @@ function GetAssistancePage(props) {
Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)}
+ onBackButtonPress={() => Navigation.goBack(navigateBackTo)}
/>
- Navigation.goBack(getFallbackRoute())}
- />
-
+
- {contentHeader}
- {contentBody}
- {shouldShowClipboard && (
-
-
-
- )}
- {shouldShowBody2 && (
-
- {translate(`referralProgram.${CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE}.body2`)}
-
- )}
- {translate('requestorStep.learnMore')}
-
-
- Navigation.goBack(getFallbackRoute())}
- pressOnEnter
- enterKeyEventListenerPriority={1}
+ }
+ headerContainerStyles={[styles.staticHeaderImage, styles.justifyContentEnd]}
+ backgroundColor={theme.PAGE_THEMES[SCREENS.RIGHT_MODAL.REFERRAL].backgroundColor}
+ >
+ {contentHeader}
+ {contentBody}
+
+ {shouldShowClipboard && (
+ Clipboard.setString(referralLink)}
/>
-
-
+ )}
+
+
{!requiresTwoFactorAuth && (
diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js
index c5e6bf43fa1d..dc8b77db4ac8 100644
--- a/src/pages/ReportDetailsPage.js
+++ b/src/pages/ReportDetailsPage.js
@@ -16,12 +16,12 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed
import RoomHeaderAvatars from '@components/RoomHeaderAvatars';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -105,7 +105,10 @@ function ReportDetailsPage(props) {
return items;
}
- if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && (!ReportUtils.isPublicRoom(props.report) || isPolicyMember))) {
+ // The Members page is only shown when:
+ // - The report is not a user created room with participants to show i.e. DM, Group Chat, etc
+ // - The report is a user created room and the room and the current user is a workspace member i.e. non-workspace members should not see this option.
+ if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && isPolicyMember)) {
items.push({
key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS,
translationKey: 'common.members',
@@ -212,7 +215,7 @@ function ReportDetailsPage(props) {
{
Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(props.report.policyID));
diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js
index ceaa53a41a6b..4ec31b29f914 100755
--- a/src/pages/ReportParticipantsPage.js
+++ b/src/pages/ReportParticipantsPage.js
@@ -9,13 +9,13 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OptionsList from '@components/OptionsList';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.js
index 957c3da9c86b..ae8a4635a98e 100644
--- a/src/pages/ReportWelcomeMessagePage.js
+++ b/src/pages/ReportWelcomeMessagePage.js
@@ -12,11 +12,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import updateMultilineInputRange from '@libs/updateMultilineInputRange';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -101,7 +101,7 @@ function ReportWelcomeMessagePage(props) {
inputID="welcomeMessage"
label={props.translate('welcomeMessagePage.welcomeMessage')}
accessibilityLabel={props.translate('welcomeMessagePage.welcomeMessage')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
autoGrowHeight
maxLength={CONST.MAX_COMMENT_LENGTH}
ref={(el) => {
diff --git a/src/pages/RoomInvitePage.js b/src/pages/RoomInvitePage.js
index 9b5b4f461652..cb72b2f8b08a 100644
--- a/src/pages/RoomInvitePage.js
+++ b/src/pages/RoomInvitePage.js
@@ -10,6 +10,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
@@ -17,7 +18,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js
index 23722625b961..d8e7dbdaf76e 100644
--- a/src/pages/RoomMembersPage.js
+++ b/src/pages/RoomMembersPage.js
@@ -13,6 +13,7 @@ import SelectionList from '@components/SelectionList';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import Log from '@libs/Log';
@@ -21,7 +22,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -237,7 +237,7 @@ function RoomMembersPage(props) {
testID={RoomMembersPage.displayName}
>
Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(props.report.reportID))}
>
diff --git a/src/pages/TeachersUnite/ImTeacherUpdateEmailPage.js b/src/pages/TeachersUnite/ImTeacherUpdateEmailPage.js
index 2dad59fc01b7..e9564bfffe0b 100644
--- a/src/pages/TeachersUnite/ImTeacherUpdateEmailPage.js
+++ b/src/pages/TeachersUnite/ImTeacherUpdateEmailPage.js
@@ -6,8 +6,8 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Illustrations from '@components/Icon/Illustrations';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
index e04b720e8365..3e2a2a2775a3 100644
--- a/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
+++ b/src/pages/TeachersUnite/IntroSchoolPrincipalPage.js
@@ -12,10 +12,10 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import TeachersUnite from '@userActions/TeachersUnite';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -107,7 +107,7 @@ function IntroSchoolPrincipalPage(props) {
name="firstName"
label={translate('teachersUnitePage.principalFirstName')}
accessibilityLabel={translate('teachersUnitePage.principalFirstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -119,7 +119,7 @@ function IntroSchoolPrincipalPage(props) {
name="lastName"
label={translate('teachersUnitePage.principalLastName')}
accessibilityLabel={translate('teachersUnitePage.principalLastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -131,7 +131,7 @@ function IntroSchoolPrincipalPage(props) {
name="partnerUserID"
label={translate('teachersUnitePage.principalWorkEmail')}
accessibilityLabel={translate('teachersUnitePage.principalWorkEmail')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.EMAIL}
autoCapitalize="none"
/>
diff --git a/src/pages/TeachersUnite/KnowATeacherPage.js b/src/pages/TeachersUnite/KnowATeacherPage.js
index 7c2b8f03f879..61e03017b7ea 100644
--- a/src/pages/TeachersUnite/KnowATeacherPage.js
+++ b/src/pages/TeachersUnite/KnowATeacherPage.js
@@ -12,11 +12,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as LoginUtils from '@libs/LoginUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import TeachersUnite from '@userActions/TeachersUnite';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -117,7 +117,7 @@ function KnowATeacherPage(props) {
name="fname"
label={translate('common.firstName')}
accessibilityLabel={translate('common.firstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -129,7 +129,7 @@ function KnowATeacherPage(props) {
name="lname"
label={translate('common.lastName')}
accessibilityLabel={translate('common.lastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
autoCapitalize="words"
/>
@@ -141,7 +141,7 @@ function KnowATeacherPage(props) {
name="partnerUserID"
label={`${translate('common.email')}/${translate('common.phoneNumber')}`}
accessibilityLabel={`${translate('common.email')}/${translate('common.phoneNumber')}`}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.EMAIL}
autoCapitalize="none"
/>
diff --git a/src/pages/TeachersUnite/SaveTheWorldPage.js b/src/pages/TeachersUnite/SaveTheWorldPage.js
index d179b7d1db95..36e03f0b4716 100644
--- a/src/pages/TeachersUnite/SaveTheWorldPage.js
+++ b/src/pages/TeachersUnite/SaveTheWorldPage.js
@@ -8,9 +8,9 @@ import LottieAnimations from '@components/LottieAnimations';
import MenuItem from '@components/MenuItem';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js
index 04aef6371074..0647310940bd 100644
--- a/src/pages/home/HeaderView.js
+++ b/src/pages/home/HeaderView.js
@@ -20,6 +20,8 @@ import Text from '@components/Text';
import ThreeDotsMenu from '@components/ThreeDotsMenu';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import {getGroupChatName} from '@libs/GroupChatUtils';
import * as HeaderUtils from '@libs/HeaderUtils';
@@ -28,8 +30,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
@@ -206,7 +206,7 @@ function HeaderView(props) {
style={[styles.LHNToggle]}
accessibilityHint={translate('accessibilityHints.navigateToChatsList')}
accessibilityLabel={translate('common.back')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{shouldShowSubscript ? (
ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true), [isOffline, reportActions]);
+
// There are no reportActions at all to display and we are still in the process of loading the next set of actions.
- const isLoadingInitialReportActions = _.isEmpty(reportActions) && reportMetadata.isLoadingInitialReportActions;
+ const isLoadingInitialReportActions = _.isEmpty(filteredReportActions) && reportMetadata.isLoadingInitialReportActions;
const isOptimisticDelete = lodashGet(report, 'statusNum') === CONST.REPORT.STATUS.CLOSED;
@@ -422,7 +427,7 @@ function ReportScreen({
>
{isReportReadyForDisplay && !isLoadingInitialReportActions && !isLoading && (
`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getReportID(route)}`,
canEvict: false,
- selector: (reportActions) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true),
},
report: {
key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${getReportID(route)}`,
diff --git a/src/pages/home/report/AnimatedEmptyStateBackground.js b/src/pages/home/report/AnimatedEmptyStateBackground.js
index 0ff401a9d3f4..7e259b7473cf 100644
--- a/src/pages/home/report/AnimatedEmptyStateBackground.js
+++ b/src/pages/home/report/AnimatedEmptyStateBackground.js
@@ -1,9 +1,9 @@
import React from 'react';
import Animated, {SensorType, useAnimatedSensor, useAnimatedStyle, useSharedValue, withSpring} from 'react-native-reanimated';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeIllustrations from '@hooks/useThemeIllustrations';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as NumberUtils from '@libs/NumberUtils';
-import useThemeIllustrations from '@styles/illustrations/useThemeIllustrations';
-import useStyleUtils from '@styles/useStyleUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js
index 33adfa4b35f9..0a9941072df7 100755
--- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js
+++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js
@@ -11,8 +11,8 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withW
import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
import compose from '@libs/compose';
-import useStyleUtils from '@styles/useStyleUtils';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js b/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js
index f5a688e9d8ed..d858206cdfc3 100644
--- a/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js
+++ b/src/pages/home/report/ContextMenu/MiniReportActionContextMenu/index.js
@@ -2,12 +2,12 @@ import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
+import useStyleUtils from '@hooks/useStyleUtils';
import BaseReportActionContextMenu from '@pages/home/report/ContextMenu/BaseReportActionContextMenu';
import {
defaultProps as GenericReportActionContextMenuDefaultProps,
propTypes as genericReportActionContextMenuPropTypes,
} from '@pages/home/report/ContextMenu/genericReportActionContextMenuPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.android.js b/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.android.js
index 873e7fa243af..700a2fb399e4 100644
--- a/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.android.js
+++ b/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.android.js
@@ -1,6 +1,6 @@
import React from 'react';
import {Animated, View} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import floatingMessageCounterContainerPropTypes from './floatingMessageCounterContainerPropTypes';
function FloatingMessageCounterContainer(props) {
diff --git a/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.js b/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.js
index 0b721067631c..19123e65cbf2 100644
--- a/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.js
+++ b/src/pages/home/report/FloatingMessageCounter/FloatingMessageCounterContainer/index.js
@@ -1,6 +1,6 @@
import React from 'react';
import {Animated} from 'react-native';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import floatingMessageCounterContainerPropTypes from './floatingMessageCounterContainerPropTypes';
function FloatingMessageCounterContainer(props) {
diff --git a/src/pages/home/report/FloatingMessageCounter/index.js b/src/pages/home/report/FloatingMessageCounter/index.js
index fe0a343e973b..07138104bf74 100644
--- a/src/pages/home/report/FloatingMessageCounter/index.js
+++ b/src/pages/home/report/FloatingMessageCounter/index.js
@@ -6,9 +6,9 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useNativeDriver from '@libs/useNativeDriver';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import FloatingMessageCounterContainer from './FloatingMessageCounterContainer';
diff --git a/src/pages/home/report/LinkPreviewer.js b/src/pages/home/report/LinkPreviewer.js
index 5c16d5596774..f62295a6fb71 100644
--- a/src/pages/home/report/LinkPreviewer.js
+++ b/src/pages/home/report/LinkPreviewer.js
@@ -5,9 +5,9 @@ import {Image, View} from 'react-native';
import _ from 'underscore';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
const IMAGE_TYPES = ['jpg', 'jpeg', 'png'];
diff --git a/src/pages/home/report/ListBoundaryLoader/ListBoundaryLoader.js b/src/pages/home/report/ListBoundaryLoader/ListBoundaryLoader.js
index 7184944d5902..77bcc7bdd38e 100644
--- a/src/pages/home/report/ListBoundaryLoader/ListBoundaryLoader.js
+++ b/src/pages/home/report/ListBoundaryLoader/ListBoundaryLoader.js
@@ -3,8 +3,8 @@ import React from 'react';
import {ActivityIndicator, View} from 'react-native';
import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView';
import useNetwork from '@hooks/useNetwork';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/home/report/ParticipantLocalTime.js b/src/pages/home/report/ParticipantLocalTime.js
index 5efd53fe6ae7..1992953c959e 100644
--- a/src/pages/home/report/ParticipantLocalTime.js
+++ b/src/pages/home/report/ParticipantLocalTime.js
@@ -4,9 +4,9 @@ import {View} from 'react-native';
import participantPropTypes from '@components/participantPropTypes';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import DateUtils from '@libs/DateUtils';
import Timers from '@libs/Timers';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/home/report/ReactionList/BaseReactionList.js b/src/pages/home/report/ReactionList/BaseReactionList.js
index f94f6cdfde0d..2d881d080c31 100755
--- a/src/pages/home/report/ReactionList/BaseReactionList.js
+++ b/src/pages/home/report/ReactionList/BaseReactionList.js
@@ -6,9 +6,9 @@ import {FlatList} from 'react-native';
import OptionRow from '@components/OptionRow';
import participantPropTypes from '@components/participantPropTypes';
import withWindowDimensions from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as UserUtils from '@libs/UserUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/home/report/ReactionList/HeaderReactionList.js b/src/pages/home/report/ReactionList/HeaderReactionList.js
index 1b1751e32eef..04b124f969a9 100644
--- a/src/pages/home/report/ReactionList/HeaderReactionList.js
+++ b/src/pages/home/report/ReactionList/HeaderReactionList.js
@@ -4,10 +4,10 @@ import {View} from 'react-native';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as EmojiUtils from '@libs/EmojiUtils';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import reactionPropTypes from './reactionPropTypes';
const propTypes = {
diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js
index e062cc2710e6..1aeae46c252f 100644
--- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js
+++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js
@@ -9,11 +9,11 @@ import PopoverMenu from '@components/PopoverMenu';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Tooltip from '@components/Tooltip/PopoverAnchorTooltip';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import * as Report from '@userActions/Report';
import * as Task from '@userActions/Task';
@@ -205,7 +205,7 @@ function AttachmentPickerWithMenuItems({
onMouseDown={(e) => e.preventDefault()}
style={styles.composerSizeButton}
disabled={isBlockedFromConcierge || disabled}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('reportActionCompose.collapse')}
>
@@ -224,7 +224,7 @@ function AttachmentPickerWithMenuItems({
onMouseDown={(e) => e.preventDefault()}
style={styles.composerSizeButton}
disabled={isBlockedFromConcierge || disabled}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('reportActionCompose.expand')}
>
@@ -244,7 +244,7 @@ function AttachmentPickerWithMenuItems({
}}
style={styles.composerSizeButton}
disabled={isBlockedFromConcierge || disabled}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('reportActionCompose.addAction')}
>
diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
index f5a321f72799..8def3a53ca0d 100644
--- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
+++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
@@ -9,7 +9,11 @@ import withKeyboardState from '@components/withKeyboardState';
import useDebounce from '@hooks/useDebounce';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
+import * as Browser from '@libs/Browser';
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
import compose from '@libs/compose';
import * as ComposerUtils from '@libs/ComposerUtils';
@@ -26,9 +30,6 @@ import updateMultilineInputRange from '@libs/updateMultilineInputRange';
import willBlurTextInputOnTapOutsideFunc from '@libs/willBlurTextInputOnTapOutside';
import SilentCommentUpdater from '@pages/home/report/ReportActionCompose/SilentCommentUpdater';
import Suggestions from '@pages/home/report/ReportActionCompose/Suggestions';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as EmojiPickerActions from '@userActions/EmojiPickerAction';
import * as InputFocus from '@userActions/InputFocus';
import * as Report from '@userActions/Report';
@@ -76,6 +77,7 @@ function ComposerWithSuggestions({
// Focus
onFocus,
onBlur,
+ onValueChange,
// Composer
isComposerFullSize,
isMenuVisible,
@@ -515,6 +517,10 @@ function ComposerWithSuggestions({
[blur, focus, prepareCommentAndResetComposer, replaceSelectionWithText],
);
+ useEffect(() => {
+ onValueChange(value);
+ }, [onValueChange, value]);
+
return (
<>
@@ -556,6 +562,7 @@ function ComposerWithSuggestions({
setComposerHeight(composerLayoutHeight);
}}
onScroll={hideSuggestionMenu}
+ shouldContainScroll={Browser.isMobileSafari()}
/>
diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose/ReportActionCompose.js
index 2632324a963f..396e94d9cf9d 100644
--- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js
+++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.js
@@ -13,7 +13,9 @@ import OfflineIndicator from '@components/OfflineIndicator';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import {usePersonalDetails, withNetwork} from '@components/OnyxProvider';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
+import useHandleExceedMaxCommentLength from '@hooks/useHandleExceedMaxCommentLength';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
import compose from '@libs/compose';
@@ -28,7 +30,6 @@ import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import ReportDropUI from '@pages/home/report/ReportDropUI';
import ReportTypingIndicator from '@pages/home/report/ReportTypingIndicator';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as EmojiPickerActions from '@userActions/EmojiPickerAction';
import * as Report from '@userActions/Report';
import * as User from '@userActions/User';
@@ -144,7 +145,7 @@ function ReportActionCompose({
* Updates the composer when the comment length is exceeded
* Shows red borders and prevents the comment from being sent
*/
- const [hasExceededMaxCommentLength, setExceededMaxCommentLength] = useState(false);
+ const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength();
const suggestionsRef = useRef(null);
const composerRef = useRef(null);
@@ -408,6 +409,7 @@ function ReportActionCompose({
onBlur={onBlur}
measureParentContainer={measureContainer}
listHeight={listHeight}
+ onValueChange={validateCommentMaxLength}
/>
{
@@ -444,10 +446,7 @@ function ReportActionCompose({
>
{!isSmallScreenWidth && }
-
+
diff --git a/src/pages/home/report/ReportActionCompose/SendButton.js b/src/pages/home/report/ReportActionCompose/SendButton.js
index 60c657ca95c7..d0b0453ace2f 100644
--- a/src/pages/home/report/ReportActionCompose/SendButton.js
+++ b/src/pages/home/report/ReportActionCompose/SendButton.js
@@ -7,8 +7,8 @@ import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
@@ -44,7 +44,7 @@ function SendButton({isDisabled: isDisabledProp, handleSendMessage}) {
isDisabledProp || pressed || isDisabled ? undefined : styles.buttonSuccess,
isDisabledProp ? styles.cursorDisabled : undefined,
]}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.send')}
>
{({pressed}) => (
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index 3e4eebffe48f..2e888a5471b8 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -32,6 +32,9 @@ import UnreadActionIndicator from '@components/UnreadActionIndicator';
import withLocalize from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import usePrevious from '@hooks/usePrevious';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import ControlSelection from '@libs/ControlSelection';
import * as CurrencyUtils from '@libs/CurrencyUtils';
@@ -46,9 +49,6 @@ import SelectionScraper from '@libs/SelectionScraper';
import userWalletPropTypes from '@pages/EnablePayments/userWalletPropTypes';
import {ReactionListContext} from '@pages/home/ReportScreenContext';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
import * as store from '@userActions/ReimbursementAccount/store';
diff --git a/src/pages/home/report/ReportActionItemBasicMessage.tsx b/src/pages/home/report/ReportActionItemBasicMessage.tsx
index bf53ee16450d..63e6d2424a7c 100644
--- a/src/pages/home/report/ReportActionItemBasicMessage.tsx
+++ b/src/pages/home/report/ReportActionItemBasicMessage.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import ChildrenProps from '@src/types/utils/ChildrenProps';
type ReportActionItemBasicMessageProps = ChildrenProps & {
diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js
index 01857e2f2f1c..e5ec3e4b8744 100644
--- a/src/pages/home/report/ReportActionItemCreated.js
+++ b/src/pages/home/report/ReportActionItemCreated.js
@@ -10,12 +10,12 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed
import ReportWelcomeText from '@components/ReportWelcomeText';
import withLocalize from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import reportWithoutHasDraftSelector from '@libs/OnyxSelectors/reportWithoutHasDraftSelector';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -76,7 +76,7 @@ function ReportActionItemCreated(props) {
onPress={() => ReportUtils.navigateToDetailsPage(props.report)}
style={[styles.mh5, styles.mb3, styles.alignSelfStart]}
accessibilityLabel={props.translate('common.details')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
disabled={shouldDisableDetailPage}
>
- {children}
-
- );
-}
-
-ReportActionItemGrouped.propTypes = propTypes;
-ReportActionItemGrouped.defaultProps = defaultProps;
-ReportActionItemGrouped.displayName = 'ReportActionItemGrouped';
-export default ReportActionItemGrouped;
diff --git a/src/pages/home/report/ReportActionItemGrouped.tsx b/src/pages/home/report/ReportActionItemGrouped.tsx
new file mode 100644
index 000000000000..2dff5b81c6a7
--- /dev/null
+++ b/src/pages/home/report/ReportActionItemGrouped.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import {StyleProp, View, ViewStyle} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
+import ChildrenProps from '@src/types/utils/ChildrenProps';
+
+type ReportActionItemGroupedProps = ChildrenProps & {
+ /** Styles for the outermost View */
+ wrapperStyle?: StyleProp;
+};
+
+function ReportActionItemGrouped({wrapperStyle, children}: ReportActionItemGroupedProps) {
+ const styles = useThemeStyles();
+ return (
+
+ {children}
+
+ );
+}
+
+ReportActionItemGrouped.displayName = 'ReportActionItemGrouped';
+
+export default ReportActionItemGrouped;
diff --git a/src/pages/home/report/ReportActionItemMessage.js b/src/pages/home/report/ReportActionItemMessage.js
index 46e0438f250a..b47d941f40b5 100644
--- a/src/pages/home/report/ReportActionItemMessage.js
+++ b/src/pages/home/report/ReportActionItemMessage.js
@@ -4,9 +4,9 @@ import React from 'react';
import {Text, View} from 'react-native';
import _ from 'underscore';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import TextCommentFragment from './comment/TextCommentFragment';
import ReportActionItemFragment from './ReportActionItemFragment';
diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js
index 13d918aa25d7..3da0fad72f0a 100644
--- a/src/pages/home/report/ReportActionItemMessageEdit.js
+++ b/src/pages/home/report/ReportActionItemMessageEdit.js
@@ -13,9 +13,13 @@ import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import refPropTypes from '@components/refPropTypes';
import Tooltip from '@components/Tooltip';
+import useHandleExceedMaxCommentLength from '@hooks/useHandleExceedMaxCommentLength';
import useKeyboardState from '@hooks/useKeyboardState';
import useLocalize from '@hooks/useLocalize';
import useReportScrollManager from '@hooks/useReportScrollManager';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import * as ComposerUtils from '@libs/ComposerUtils';
@@ -27,9 +31,6 @@ import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import setShouldShowComposeInputKeyboardAware from '@libs/setShouldShowComposeInputKeyboardAware';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
import * as InputFocus from '@userActions/InputFocus';
import * as Report from '@userActions/Report';
@@ -116,7 +117,7 @@ function ReportActionItemMessageEdit(props) {
});
const [selection, setSelection] = useState(getInitialSelection);
const [isFocused, setIsFocused] = useState(false);
- const [hasExceededMaxCommentLength, setHasExceededMaxCommentLength] = useState(false);
+ const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength();
const [modal, setModal] = useState(false);
const [onyxFocused, setOnyxFocused] = useState(false);
@@ -369,6 +370,10 @@ function ReportActionItemMessageEdit(props) {
*/
const focus = focusComposerWithDelay(textInputRef.current);
+ useEffect(() => {
+ validateCommentMaxLength(draft);
+ }, [draft, validateCommentMaxLength]);
+
return (
<>
@@ -386,7 +391,7 @@ function ReportActionItemMessageEdit(props) {
- setHasExceededMaxCommentLength(hasExceeded)}
- />
+
>
);
}
diff --git a/src/pages/home/report/ReportActionItemParentAction.js b/src/pages/home/report/ReportActionItemParentAction.js
index 4a125d1d5633..c11200ccc4db 100644
--- a/src/pages/home/report/ReportActionItemParentAction.js
+++ b/src/pages/home/report/ReportActionItemParentAction.js
@@ -6,11 +6,11 @@ import {withOnyx} from 'react-native-onyx';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import withLocalize from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import ONYXKEYS from '@src/ONYXKEYS';
import AnimatedEmptyStateBackground from './AnimatedEmptyStateBackground';
diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js
index 03603f201edf..81827073aa49 100644
--- a/src/pages/home/report/ReportActionItemSingle.js
+++ b/src/pages/home/report/ReportActionItemSingle.js
@@ -13,6 +13,9 @@ import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import UserDetailsTooltip from '@components/UserDetailsTooltip';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import ControlSelection from '@libs/ControlSelection';
import DateUtils from '@libs/DateUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -20,9 +23,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import reportPropTypes from '@pages/reportPropTypes';
import stylePropTypes from '@styles/stylePropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import ReportActionItemDate from './ReportActionItemDate';
@@ -217,7 +217,7 @@ function ReportActionItemSingle(props) {
onPress={showActorDetails}
disabled={shouldDisableDetailPage}
accessibilityLabel={actorHint}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{getAvatar()}
@@ -231,7 +231,7 @@ function ReportActionItemSingle(props) {
onPress={showActorDetails}
disabled={shouldDisableDetailPage}
accessibilityLabel={actorHint}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
{_.map(personArray, (fragment, index) => (
{
Report.navigateToAndOpenChildReport(props.childReportID);
}}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={`${props.numberOfReplies} ${replyText}`}
onSecondaryInteraction={props.onSecondaryInteraction}
>
diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js
index 55995a8059e7..46abbfc71b84 100644
--- a/src/pages/home/report/ReportActionsList.js
+++ b/src/pages/home/report/ReportActionsList.js
@@ -12,12 +12,12 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withW
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useReportScrollManager from '@hooks/useReportScrollManager';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import DateUtils from '@libs/DateUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
diff --git a/src/pages/home/report/ReportDropUI.js b/src/pages/home/report/ReportDropUI.js
index 2f4c81313ec2..c1c3b8e506ab 100644
--- a/src/pages/home/report/ReportDropUI.js
+++ b/src/pages/home/report/ReportDropUI.js
@@ -6,7 +6,7 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
const propTypes = {
/** Callback to execute when a file is dropped. */
diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js
index e5dd5da19ad5..48bfd5d18bcc 100644
--- a/src/pages/home/report/ReportFooter.js
+++ b/src/pages/home/report/ReportFooter.js
@@ -9,10 +9,10 @@ import participantPropTypes from '@components/participantPropTypes';
import SwipeableView from '@components/SwipeableView';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/home/report/ReportTypingIndicator.js b/src/pages/home/report/ReportTypingIndicator.js
index 3a2c611ac358..74778b364db1 100755
--- a/src/pages/home/report/ReportTypingIndicator.js
+++ b/src/pages/home/report/ReportTypingIndicator.js
@@ -7,8 +7,8 @@ import {withNetwork} from '@components/OnyxProvider';
import Text from '@components/Text';
import TextWithEllipsis from '@components/TextWithEllipsis';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/home/report/comment/AttachmentCommentFragment.js b/src/pages/home/report/comment/AttachmentCommentFragment.js
index ec75edd18a35..30c131b57060 100644
--- a/src/pages/home/report/comment/AttachmentCommentFragment.js
+++ b/src/pages/home/report/comment/AttachmentCommentFragment.js
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
+import useThemeStyles from '@hooks/useThemeStyles';
import reportActionSourcePropType from '@pages/home/report/reportActionSourcePropType';
-import useThemeStyles from '@styles/useThemeStyles';
import RenderCommentHTML from './RenderCommentHTML';
const propTypes = {
diff --git a/src/pages/home/report/comment/TextCommentFragment.js b/src/pages/home/report/comment/TextCommentFragment.js
index 403c470dfc9d..3d6482344450 100644
--- a/src/pages/home/report/comment/TextCommentFragment.js
+++ b/src/pages/home/report/comment/TextCommentFragment.js
@@ -5,15 +5,14 @@ import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import ZeroWidthView from '@components/ZeroWidthView';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import convertToLTR from '@libs/convertToLTR';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as EmojiUtils from '@libs/EmojiUtils';
import reportActionFragmentPropTypes from '@pages/home/report/reportActionFragmentPropTypes';
import reportActionSourcePropType from '@pages/home/report/reportActionSourcePropType';
-import editedLabelStyles from '@styles/editedLabelStyles';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import RenderCommentHTML from './RenderCommentHTML';
@@ -103,7 +102,7 @@ function TextCommentFragment(props) {
{props.translate('reportActionCompose.edited')}
diff --git a/src/pages/home/sidebar/AvatarWithOptionalStatus.js b/src/pages/home/sidebar/AvatarWithOptionalStatus.js
index 4507b21a382c..0bad9e845e9c 100644
--- a/src/pages/home/sidebar/AvatarWithOptionalStatus.js
+++ b/src/pages/home/sidebar/AvatarWithOptionalStatus.js
@@ -4,9 +4,10 @@ import React, {useCallback} from 'react';
import {View} from 'react-native';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Text from '@components/Text';
+import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import PressableAvatarWithIndicator from './PressableAvatarWithIndicator';
@@ -42,18 +43,20 @@ function AvatarWithOptionalStatus({emojiStatus, isCreateMenuOpen}) {
-
-
- {emojiStatus}
-
-
+
+
+
+ {emojiStatus}
+
+
+
diff --git a/src/pages/home/sidebar/PressableAvatarWithIndicator.js b/src/pages/home/sidebar/PressableAvatarWithIndicator.js
index ddf89321b680..d72aef2ef824 100644
--- a/src/pages/home/sidebar/PressableAvatarWithIndicator.js
+++ b/src/pages/home/sidebar/PressableAvatarWithIndicator.js
@@ -52,7 +52,7 @@ function PressableAvatarWithIndicator({isCreateMenuOpen, currentUserPersonalDeta
return (
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index e9a4b75732e0..eb4f9000d2b4 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -12,6 +12,9 @@ import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Tooltip from '@components/Tooltip';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import KeyboardShortcut from '@libs/KeyboardShortcut';
import Navigation from '@libs/Navigation/Navigation';
@@ -19,9 +22,6 @@ import onyxSubscribe from '@libs/onyxSubscribe';
import SidebarUtils from '@libs/SidebarUtils';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import safeAreaInsetPropTypes from '@pages/safeAreaInsetPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as App from '@userActions/App';
import * as Session from '@userActions/Session';
@@ -163,13 +163,13 @@ function SidebarLinks({onLinkClick, insets, optionListItems, isLoading, priority
height={variables.lhnLogoHeight}
/>
}
- accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
shouldShowEnvironmentBadge
/>
diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js
index 97f119bbd2e8..dbc77a41817b 100644
--- a/src/pages/home/sidebar/SidebarLinksData.js
+++ b/src/pages/home/sidebar/SidebarLinksData.js
@@ -10,10 +10,10 @@ import {withNetwork} from '@components/OnyxProvider';
import withCurrentReportID from '@components/withCurrentReportID';
import withNavigationFocus from '@components/withNavigationFocus';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import SidebarUtils from '@libs/SidebarUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import SidebarLinks, {basePropTypes} from './SidebarLinks';
diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
index 5b7a126a4655..a6853316b582 100644
--- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
+++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
@@ -1,10 +1,10 @@
import React, {useEffect} from 'react';
import {View} from 'react-native';
import ScreenWrapper from '@components/ScreenWrapper';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import Performance from '@libs/Performance';
import SidebarLinksData from '@pages/home/sidebar/SidebarLinksData';
-import useThemeStyles from '@styles/useThemeStyles';
import Timing from '@userActions/Timing';
import CONST from '@src/CONST';
import sidebarPropTypes from './sidebarPropTypes';
diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
index ae517f156c65..65b79ed5af78 100644
--- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
+++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js
@@ -11,10 +11,10 @@ import withNavigation from '@components/withNavigation';
import withNavigationFocus from '@components/withNavigationFocus';
import withWindowDimensions from '@components/withWindowDimensions';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as App from '@userActions/App';
import * as IOU from '@userActions/IOU';
import * as Policy from '@userActions/Policy';
@@ -240,7 +240,7 @@ function FloatingActionButtonAndPopover(props) {
/>
{
diff --git a/src/pages/home/sidebar/SignInButton.js b/src/pages/home/sidebar/SignInButton.js
index c42e56551200..9edcc9584dbd 100644
--- a/src/pages/home/sidebar/SignInButton.js
+++ b/src/pages/home/sidebar/SignInButton.js
@@ -4,7 +4,7 @@ import {View} from 'react-native';
import Button from '@components/Button';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
@@ -15,7 +15,7 @@ function SignInButton() {
return (
diff --git a/src/pages/iou/MoneyRequestCategoryPage.js b/src/pages/iou/MoneyRequestCategoryPage.js
index 7f3bf7985ba6..ceb2152d2b49 100644
--- a/src/pages/iou/MoneyRequestCategoryPage.js
+++ b/src/pages/iou/MoneyRequestCategoryPage.js
@@ -7,10 +7,10 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/iou/MoneyRequestDatePage.js b/src/pages/iou/MoneyRequestDatePage.js
index 8121bb381f32..b7d1c4002da1 100644
--- a/src/pages/iou/MoneyRequestDatePage.js
+++ b/src/pages/iou/MoneyRequestDatePage.js
@@ -8,9 +8,9 @@ import FormProvider from '@components/Form/FormProvider';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/iou/MoneyRequestDescriptionPage.js b/src/pages/iou/MoneyRequestDescriptionPage.js
index 4bfcc7b5f12d..fe3100b8c3bd 100644
--- a/src/pages/iou/MoneyRequestDescriptionPage.js
+++ b/src/pages/iou/MoneyRequestDescriptionPage.js
@@ -11,12 +11,12 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as IOU from '@libs/actions/IOU';
import * as Browser from '@libs/Browser';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import updateMultilineInputRange from '@libs/updateMultilineInputRange';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -132,7 +132,7 @@ function MoneyRequestDescriptionPage({iou, route, selectedTab}) {
defaultValue={iou.comment}
label={translate('moneyRequestConfirmationList.whatsItFor')}
accessibilityLabel={translate('moneyRequestConfirmationList.whatsItFor')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(el) => {
if (!el) {
return;
diff --git a/src/pages/iou/MoneyRequestMerchantPage.js b/src/pages/iou/MoneyRequestMerchantPage.js
index 2c5869dfa7a3..bf799cd0957b 100644
--- a/src/pages/iou/MoneyRequestMerchantPage.js
+++ b/src/pages/iou/MoneyRequestMerchantPage.js
@@ -11,8 +11,8 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -118,7 +118,7 @@ function MoneyRequestMerchantPage({iou, route}) {
maxLength={CONST.MERCHANT_NAME_MAX_LENGTH}
label={translate('common.merchant')}
accessibilityLabel={translate('common.merchant')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={inputCallbackRef}
/>
diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js
index ee4ee88d7008..e367709cb010 100644
--- a/src/pages/iou/MoneyRequestSelectorPage.js
+++ b/src/pages/iou/MoneyRequestSelectorPage.js
@@ -11,6 +11,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TabSelector from '@components/TabSelector/TabSelector';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as IOUUtils from '@libs/IOUUtils';
@@ -19,7 +20,6 @@ import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator';
import * as ReportUtils from '@libs/ReportUtils';
import withReportOrNotFound from '@pages/home/report/withReportOrNotFound';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/iou/MoneyRequestTagPage.js b/src/pages/iou/MoneyRequestTagPage.js
index d16a7aa6679c..60e40d665580 100644
--- a/src/pages/iou/MoneyRequestTagPage.js
+++ b/src/pages/iou/MoneyRequestTagPage.js
@@ -9,11 +9,11 @@ import TagPicker from '@components/TagPicker';
import tagPropTypes from '@components/tagPropTypes';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/iou/ReceiptDropUI.js b/src/pages/iou/ReceiptDropUI.js
index 18ad31e036e4..67330860a052 100644
--- a/src/pages/iou/ReceiptDropUI.js
+++ b/src/pages/iou/ReceiptDropUI.js
@@ -4,7 +4,7 @@ import {Text, View} from 'react-native';
import ReceiptUpload from '@assets/images/receipt-upload.svg';
import DragAndDropConsumer from '@components/DragAndDrop/Consumer';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/iou/ReceiptSelector/index.js b/src/pages/iou/ReceiptSelector/index.js
index dd7c2e3a104e..adbfc0618de7 100644
--- a/src/pages/iou/ReceiptSelector/index.js
+++ b/src/pages/iou/ReceiptSelector/index.js
@@ -15,6 +15,8 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import * as FileUtils from '@libs/fileDownload/FileUtils';
@@ -22,8 +24,6 @@ import Navigation from '@libs/Navigation/Navigation';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
import ReceiptDropUI from '@pages/iou/ReceiptDropUI';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -208,7 +208,7 @@ function ReceiptSelector({route, transactionID, iou, report}) {
{({openPicker}) => (
{
openPicker({
onPicked: (file) => {
@@ -227,7 +227,7 @@ function ReceiptSelector({route, transactionID, iou, report}) {
)}
{({openPicker}) => (
{
@@ -255,7 +255,7 @@ function ReceiptSelector({route, report, iou, transactionID}) {
)}
`${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(route, 'params.transactionID')}`,
- selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
},
recentWaypoints: {
key: ONYXKEYS.NVP_RECENT_WAYPOINTS,
diff --git a/src/pages/iou/request/IOURequestStartPage.js b/src/pages/iou/request/IOURequestStartPage.js
index 48efc0bdd17c..6572e154ee14 100644
--- a/src/pages/iou/request/IOURequestStartPage.js
+++ b/src/pages/iou/request/IOURequestStartPage.js
@@ -6,12 +6,14 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TabSelector from '@components/TabSelector/TabSelector';
import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -19,7 +21,6 @@ import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -108,6 +109,12 @@ function IOURequestStartPage({
[previousIOURequestType, reportID, isFromGlobalCreate],
);
+ if (!transaction.transactionID) {
+ // The draft transaction is initialized only after the component is mounted,
+ // which will lead to briefly displaying the Not Found page without this loader.
+ return ;
+ }
+
return (
participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase())),
+ _.some(participants, (participant) => lodashGet(participant, 'searchText', '').toLowerCase().includes(searchTerm.trim().toLowerCase())),
);
const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails);
diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js
index 913912fcf05c..8f89703e6efd 100644
--- a/src/pages/iou/request/step/IOURequestStepAmount.js
+++ b/src/pages/iou/request/step/IOURequestStepAmount.js
@@ -99,6 +99,7 @@ function IOURequestStepAmount({
onBackButtonPress={navigateBack}
testID={IOURequestStepAmount.displayName}
shouldShowWrapper={Boolean(backTo)}
+ includeSafeAreaPaddingBottom
>
optionsSelectorRef.current && optionsSelectorRef.current.focus()}
+ includeSafeAreaPaddingBottom
>
(optionsSelectorRef.current = el)}
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.js b/src/pages/iou/request/step/IOURequestStepScan/index.js
index 5098401ddf79..c51727f0143b 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.js
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.js
@@ -13,6 +13,8 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
@@ -24,8 +26,6 @@ import StepScreenDragAndDropWrapper from '@pages/iou/request/step/StepScreenDrag
import withFullTransactionOrNotFound from '@pages/iou/request/step/withFullTransactionOrNotFound';
import withWritableReportOrNotFound from '@pages/iou/request/step/withWritableReportOrNotFound';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
@@ -154,6 +154,11 @@ function IOURequestStepScan({
const fileSource = URL.createObjectURL(imageFile);
IOU.setMoneyRequestReceipt_temporaryForRefactor(transactionID, fileSource, imageFile.name);
+ if (backTo) {
+ Navigation.goBack(backTo);
+ return;
+ }
+
// When an existing transaction is being edited (eg. not the create transaction flow)
if (transactionID !== CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
IOU.replaceReceipt(transactionID, imageFile, fileSource);
@@ -171,7 +176,7 @@ function IOURequestStepScan({
}
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID));
- }, [cameraRef, report, iouType, transactionID, reportID]);
+ }, [cameraRef, report, iouType, transactionID, reportID, backTo]);
const panResponder = useRef(
PanResponder.create({
diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.js b/src/pages/iou/request/step/IOURequestStepScan/index.native.js
index 65a0ffd7bf59..8745600924e8 100644
--- a/src/pages/iou/request/step/IOURequestStepScan/index.native.js
+++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.js
@@ -11,6 +11,8 @@ import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as FileUtils from '@libs/fileDownload/FileUtils';
import Log from '@libs/Log';
@@ -20,8 +22,6 @@ import StepScreenWrapper from '@pages/iou/request/step/StepScreenWrapper';
import withFullTransactionOrNotFound from '@pages/iou/request/step/withFullTransactionOrNotFound';
import withWritableReportOrNotFound from '@pages/iou/request/step/withWritableReportOrNotFound';
import reportPropTypes from '@pages/reportPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
@@ -214,14 +214,18 @@ function IOURequestStepScan({
)}
{cameraPermissionStatus === RESULTS.GRANTED && device != null && (
-
+
+
+
+
+
)}
@@ -239,6 +243,11 @@ function IOURequestStepScan({
const filePath = file.uri;
IOU.setMoneyRequestReceipt_temporaryForRefactor(transactionID, filePath, file.name);
+ if (backTo) {
+ Navigation.goBack(backTo);
+ return;
+ }
+
// When a transaction is being edited (eg. not in the creation flow)
if (transactionID !== CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
IOU.replaceReceipt(transactionID, file, filePath);
diff --git a/src/pages/iou/request/step/IOURequestStepTag.js b/src/pages/iou/request/step/IOURequestStepTag.js
index 12e5dc8f9dab..7e2ccbe1a9dd 100644
--- a/src/pages/iou/request/step/IOURequestStepTag.js
+++ b/src/pages/iou/request/step/IOURequestStepTag.js
@@ -6,11 +6,11 @@ import tagPropTypes from '@components/tagPropTypes';
import Text from '@components/Text';
import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.js b/src/pages/iou/request/step/IOURequestStepWaypoint.js
index 7af58a7e0352..dc5b9f7d6275 100644
--- a/src/pages/iou/request/step/IOURequestStepWaypoint.js
+++ b/src/pages/iou/request/step/IOURequestStepWaypoint.js
@@ -16,12 +16,12 @@ import ScreenWrapper from '@components/ScreenWrapper';
import transactionPropTypes from '@components/transactionPropTypes';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Transaction from '@userActions/Transaction';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/iou/request/step/StepScreenDragAndDropWrapper.js b/src/pages/iou/request/step/StepScreenDragAndDropWrapper.js
index a369775d7110..ceb0d5a44351 100644
--- a/src/pages/iou/request/step/StepScreenDragAndDropWrapper.js
+++ b/src/pages/iou/request/step/StepScreenDragAndDropWrapper.js
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** The things to display inside the screenwrapper */
@@ -32,9 +32,10 @@ const defaultProps = {
};
function StepScreenDragAndDropWrapper({testID, headerTitle, onBackButtonPress, onEntryTransitionEnd, children, shouldShowWrapper}) {
- const [isDraggingOver, setIsDraggingOver] = useState(false);
const styles = useThemeStyles();
+ const [isDraggingOver, setIsDraggingOver] = useState(false);
+
if (!shouldShowWrapper) {
return children;
}
diff --git a/src/pages/iou/request/step/StepScreenWrapper.js b/src/pages/iou/request/step/StepScreenWrapper.js
index 000beb8432c5..eae542f0f6f9 100644
--- a/src/pages/iou/request/step/StepScreenWrapper.js
+++ b/src/pages/iou/request/step/StepScreenWrapper.js
@@ -4,8 +4,8 @@ import {View} from 'react-native';
import _ from 'underscore';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
-import useThemeStyles from '@styles/useThemeStyles';
const propTypes = {
/** The things to display inside the screenwrapper */
@@ -25,13 +25,17 @@ const propTypes = {
/** An ID used for unit testing */
testID: PropTypes.string.isRequired,
+
+ /** Whether or not to include safe area padding */
+ includeSafeAreaPaddingBottom: PropTypes.bool,
};
const defaultProps = {
onEntryTransitionEnd: () => {},
+ includeSafeAreaPaddingBottom: false,
};
-function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTransitionEnd, children, shouldShowWrapper}) {
+function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTransitionEnd, children, shouldShowWrapper, includeSafeAreaPaddingBottom}) {
const styles = useThemeStyles();
if (!shouldShowWrapper) {
@@ -40,14 +44,13 @@ function StepScreenWrapper({testID, headerTitle, onBackButtonPress, onEntryTrans
return (
{({insets, safeAreaPaddingBottomStyle, didScreenTransitionEnd}) => (
-
+ ;
+ return ;
}
return (
diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js
index a8e56f7a41e8..c9075d896deb 100644
--- a/src/pages/iou/steps/MoneyRequestAmountForm.js
+++ b/src/pages/iou/steps/MoneyRequestAmountForm.js
@@ -9,13 +9,13 @@ import FormHelpMessage from '@components/FormHelpMessage';
import refPropTypes from '@components/refPropTypes';
import TextInputWithCurrencySymbol from '@components/TextInputWithCurrencySymbol';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import getOperatingSystem from '@libs/getOperatingSystem';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
const propTypes = {
diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js
index 03ebb9bdb562..3476b2304875 100644
--- a/src/pages/iou/steps/MoneyRequestConfirmPage.js
+++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js
@@ -13,6 +13,7 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro
import withLocalize from '@components/withLocalize';
import useInitialValue from '@hooks/useInitialValue';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import * as FileUtils from '@libs/fileDownload/FileUtils';
@@ -22,7 +23,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js
index d44c40db209f..7826643d4283 100644
--- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js
+++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js
@@ -10,13 +10,13 @@ import ScreenWrapper from '@components/ScreenWrapper';
import transactionPropTypes from '@components/transactionPropTypes';
import useInitialValue from '@hooks/useInitialValue';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as TransactionUtils from '@libs/TransactionUtils';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
index a8b4dae0facc..d8d644479270 100755
--- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
+++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
@@ -10,6 +10,7 @@ import OptionsSelector from '@components/OptionsSelector';
import refPropTypes from '@components/refPropTypes';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Report from '@libs/actions/Report';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
@@ -17,7 +18,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import personalDetailsPropType from '@pages/personalDetailsPropType';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/iou/steps/NewRequestAmountPage.js b/src/pages/iou/steps/NewRequestAmountPage.js
index bf92c420e82c..569e2ce693ee 100644
--- a/src/pages/iou/steps/NewRequestAmountPage.js
+++ b/src/pages/iou/steps/NewRequestAmountPage.js
@@ -9,13 +9,13 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as IOUUtils from '@libs/IOUUtils';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/AboutPage/AboutPage.js b/src/pages/settings/AboutPage/AboutPage.js
index c192abf84e43..16ae590cf86b 100644
--- a/src/pages/settings/AboutPage/AboutPage.js
+++ b/src/pages/settings/AboutPage/AboutPage.js
@@ -11,13 +11,13 @@ import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
import compose from '@libs/compose';
import * as Environment from '@libs/Environment/Environment';
import Navigation from '@libs/Navigation/Navigation';
import {CONTEXT_MENU_TYPES} from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/AppDownloadLinks.js b/src/pages/settings/AppDownloadLinks.js
index 182a25a121b5..471a38b039b2 100644
--- a/src/pages/settings/AppDownloadLinks.js
+++ b/src/pages/settings/AppDownloadLinks.js
@@ -7,11 +7,11 @@ import MenuItem from '@components/MenuItem';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import {CONTEXT_MENU_TYPES} from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js
index 8ca1f96b3796..ede356f3bb02 100755
--- a/src/pages/settings/InitialSettingsPage.js
+++ b/src/pages/settings/InitialSettingsPage.js
@@ -21,7 +21,10 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useLocalize from '@hooks/useLocalize';
import useSingleExecution from '@hooks/useSingleExecution';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
+import * as CardUtils from '@libs/CardUtils';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -33,8 +36,6 @@ import {CONTEXT_MENU_TYPES} from '@pages/home/report/ContextMenu/ContextMenuActi
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import policyMemberPropType from '@pages/policyMemberPropType';
import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import * as PaymentMethods from '@userActions/PaymentMethods';
import * as Session from '@userActions/Session';
@@ -43,6 +44,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
+import assignedCardPropTypes from './Wallet/assignedCardPropTypes';
const propTypes = {
/* Onyx Props */
@@ -102,6 +104,8 @@ const propTypes = {
}),
),
+ cardList: PropTypes.objectOf(assignedCardPropTypes),
+
/** Members keyed by accountID for all policies */
allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)),
@@ -120,6 +124,7 @@ const defaultProps = {
bankAccountList: {},
fundList: null,
loginList: {},
+ cardList: {},
allPolicyMembers: {},
...withCurrentUserPersonalDetailsDefaultProps,
};
@@ -235,7 +240,10 @@ function InitialSettingsPage(props) {
Navigation.navigate(ROUTES.SETTINGS_WALLET);
}),
brickRoadIndicator:
- PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList) || !_.isEmpty(props.userWallet.errors) || !_.isEmpty(props.walletTerms.errors)
+ PaymentMethods.hasPaymentMethodError(props.bankAccountList, paymentCardList) ||
+ !_.isEmpty(props.userWallet.errors) ||
+ !_.isEmpty(props.walletTerms.errors) ||
+ CardUtils.hasDetectedFraud(props.cardList)
? 'error'
: null,
},
@@ -267,6 +275,7 @@ function InitialSettingsPage(props) {
}, [
props.allPolicyMembers,
props.bankAccountList,
+ props.cardList,
props.fundList,
props.loginList,
props.network.isOffline,
@@ -335,7 +344,7 @@ function InitialSettingsPage(props) {
disabled={isExecuting}
onPress={singleExecution(openProfileSettings)}
accessibilityLabel={translate('common.profile')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
Navigation.navigate(ROUTES.SETTINGS_LANGUAGE)}
/>
+ Navigation.navigate(ROUTES.SETTINGS_THEME)}
+ />
{/* Enable additional test features in non-production environments */}
{!isProduction && (
@@ -102,4 +112,7 @@ export default withOnyx({
user: {
key: ONYXKEYS.USER,
},
+ preferredTheme: {
+ key: ONYXKEYS.PREFERRED_THEME,
+ },
})(PreferencesPage);
diff --git a/src/pages/settings/Preferences/PriorityModePage.js b/src/pages/settings/Preferences/PriorityModePage.js
index 0778394d2b28..2a9d9c5b0d9e 100644
--- a/src/pages/settings/Preferences/PriorityModePage.js
+++ b/src/pages/settings/Preferences/PriorityModePage.js
@@ -7,8 +7,8 @@ import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Preferences/ThemePage.js b/src/pages/settings/Preferences/ThemePage.js
index f4acd10a7230..453bf0a72aa8 100644
--- a/src/pages/settings/Preferences/ThemePage.js
+++ b/src/pages/settings/Preferences/ThemePage.js
@@ -6,18 +6,15 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import Text from '@components/Text';
-import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import compose from '@libs/compose';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
const propTypes = {
- ...withLocalizePropTypes,
-
/** The theme of the app */
preferredTheme: PropTypes.string,
};
@@ -28,9 +25,10 @@ const defaultProps = {
function ThemePage(props) {
const styles = useThemeStyles();
- const localesToThemes = _.map(_.values(_.omit(CONST.THEME, 'DEFAULT')), (theme) => ({
+ const {translate} = useLocalize();
+ const localesToThemes = _.map(_.values(_.omit(CONST.THEME, 'DEFAULT', 'FALLBACK')), (theme) => ({
value: theme,
- text: props.translate(`themePage.themes.${theme}.label`),
+ text: translate(`themePage.themes.${theme}.label`),
keyForList: theme,
isSelected: (props.preferredTheme || CONST.THEME.DEFAULT) === theme,
}));
@@ -41,13 +39,13 @@ function ThemePage(props) {
testID={ThemePage.displayName}
>
Navigation.navigate(ROUTES.SETTINGS_PREFERENCES)}
onCloseButtonPress={() => Navigation.dismissModal(true)}
/>
- {props.translate('themePage.chooseThemeBelowOrSync')}
+ {translate('themePage.chooseThemeBelowOrSync')} (loginInputRef.current = el)}
inputID="phoneOrEmail"
diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
index fa1c17578126..d15405f8029c 100644
--- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
+++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js
@@ -13,12 +13,12 @@ import {withNetwork} from '@components/OnyxProvider';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
@@ -207,7 +207,7 @@ function BaseValidateCodeForm(props) {
underlayColor={theme.componentBG}
hoverDimmingValue={1}
pressDimmingValue={0.2}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('validateCodeForm.magicCodeNotReceived')}
>
{props.translate('validateCodeForm.magicCodeNotReceived')}
diff --git a/src/pages/settings/Profile/CustomStatus/SetDatePage.js b/src/pages/settings/Profile/CustomStatus/SetDatePage.js
new file mode 100644
index 000000000000..8839f1289490
--- /dev/null
+++ b/src/pages/settings/Profile/CustomStatus/SetDatePage.js
@@ -0,0 +1,88 @@
+import lodashGet from 'lodash/get';
+import React, {useCallback} from 'react';
+import {withOnyx} from 'react-native-onyx';
+import DatePicker from '@components/DatePicker';
+import FormProvider from '@components/Form/FormProvider';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import * as User from '@libs/actions/User';
+import compose from '@libs/compose';
+import DateUtils from '@libs/DateUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import * as ValidationUtils from '@libs/ValidationUtils';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+
+const propTypes = {
+ ...withLocalizePropTypes,
+};
+
+function SetDatePage({translate, customStatus}) {
+ const styles = useThemeStyles();
+ const customClearAfter = lodashGet(customStatus, 'clearAfter', '');
+
+ const onSubmit = (v) => {
+ User.updateDraftCustomStatus({clearAfter: DateUtils.combineDateAndTime(customClearAfter, v.dateTime)});
+ Navigation.goBack(ROUTES.SETTINGS_STATUS_CLEAR_AFTER);
+ };
+
+ const validate = useCallback((values) => {
+ const requiredFields = ['dateTime'];
+ const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
+ const dateError = ValidationUtils.getDatePassedError(values.dateTime);
+
+ if (values.dateTime && dateError) {
+ errors.dateTime = dateError;
+ }
+
+ return errors;
+ }, []);
+
+ return (
+
+ Navigation.goBack(ROUTES.SETTINGS_STATUS_CLEAR_AFTER)}
+ />
+
+
+
+
+ );
+}
+
+SetDatePage.propTypes = propTypes;
+SetDatePage.displayName = 'SetDatePage';
+
+export default compose(
+ withLocalize,
+ withOnyx({
+ privatePersonalDetails: {
+ key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
+ },
+ customStatus: {
+ key: ONYXKEYS.CUSTOM_STATUS_DRAFT,
+ },
+ clearDateForm: {
+ key: `${ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_DATE_FORM}Draft`,
+ },
+ }),
+)(SetDatePage);
diff --git a/src/pages/settings/Profile/CustomStatus/SetTimePage.js b/src/pages/settings/Profile/CustomStatus/SetTimePage.js
new file mode 100644
index 000000000000..3cdf739ac7b9
--- /dev/null
+++ b/src/pages/settings/Profile/CustomStatus/SetTimePage.js
@@ -0,0 +1,73 @@
+import lodashGet from 'lodash/get';
+import React from 'react';
+import {View} from 'react-native';
+import {withOnyx} from 'react-native-onyx';
+import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TimePicker from '@components/TimePicker/TimePicker';
+import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
+import * as User from '@libs/actions/User';
+import compose from '@libs/compose';
+import DateUtils from '@libs/DateUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+
+const propTypes = {
+ ...withLocalizePropTypes,
+};
+
+function SetTimePage({translate, privatePersonalDetails, customStatus}) {
+ usePrivatePersonalDetails();
+
+ const styles = useThemeStyles();
+ const clearAfter = lodashGet(customStatus, 'clearAfter', '');
+
+ const onSubmit = (time) => {
+ const timeToUse = DateUtils.combineDateAndTime(time, clearAfter);
+
+ User.updateDraftCustomStatus({clearAfter: timeToUse});
+ Navigation.goBack(ROUTES.SETTINGS_STATUS_CLEAR_AFTER);
+ };
+
+ if (lodashGet(privatePersonalDetails, 'isLoading', true)) {
+ return ;
+ }
+ return (
+
+ Navigation.goBack(ROUTES.SETTINGS_STATUS_CLEAR_AFTER)}
+ />
+
+
+
+
+ );
+}
+
+SetTimePage.propTypes = propTypes;
+SetTimePage.displayName = 'SetTimePage';
+
+export default compose(
+ withLocalize,
+ withOnyx({
+ privatePersonalDetails: {
+ key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
+ },
+ customStatus: {
+ key: ONYXKEYS.CUSTOM_STATUS_DRAFT,
+ },
+ }),
+)(SetTimePage);
diff --git a/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.js b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.js
new file mode 100644
index 000000000000..569435048383
--- /dev/null
+++ b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.js
@@ -0,0 +1,247 @@
+import _ from 'lodash';
+import lodashGet from 'lodash/get';
+import PropTypes from 'prop-types';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
+import {View} from 'react-native';
+import {withOnyx} from 'react-native-onyx';
+import FormProvider from '@components/Form/FormProvider';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import ScreenWrapper from '@components/ScreenWrapper';
+import BaseListItem from '@components/SelectionList/BaseListItem';
+import Text from '@components/Text';
+import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps} from '@components/withCurrentUserPersonalDetails';
+import withLocalize from '@components/withLocalize';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import * as User from '@libs/actions/User';
+import compose from '@libs/compose';
+import DateUtils from '@libs/DateUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import * as ValidationUtils from '@libs/ValidationUtils';
+import personalDetailsPropType from '@pages/personalDetailsPropType';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+
+const defaultProps = {
+ ...withCurrentUserPersonalDetailsDefaultProps,
+};
+
+const propTypes = {
+ currentUserPersonalDetails: personalDetailsPropType,
+ customStatus: PropTypes.shape({
+ clearAfter: PropTypes.string,
+ }),
+};
+
+/**
+ * @param {string} data - either a value from CONST.CUSTOM_STATUS_TYPES or a dateTime string in the format YYYY-MM-DD HH:mm
+ * @returns {string}
+ */
+function getSelectedStatusType(data) {
+ switch (data) {
+ case DateUtils.getEndOfToday():
+ return CONST.CUSTOM_STATUS_TYPES.AFTER_TODAY;
+ case CONST.CUSTOM_STATUS_TYPES.NEVER:
+ case '':
+ return CONST.CUSTOM_STATUS_TYPES.NEVER;
+ case false:
+ return CONST.CUSTOM_STATUS_TYPES.AFTER_TODAY;
+ default:
+ return CONST.CUSTOM_STATUS_TYPES.CUSTOM;
+ }
+}
+
+const useValidateCustomDate = (data) => {
+ const {translate} = useLocalize();
+ const [customDateError, setCustomDateError] = useState('');
+ const [customTimeError, setCustomTimeError] = useState('');
+ const validate = () => {
+ const {dateValidationErrorKey, timeValidationErrorKey} = ValidationUtils.validateDateTimeIsAtLeastOneMinuteInFuture(data);
+
+ const dateError = dateValidationErrorKey ? translate(dateValidationErrorKey) : '';
+ setCustomDateError(dateError);
+
+ const timeError = timeValidationErrorKey ? translate(timeValidationErrorKey) : '';
+ setCustomTimeError(timeError);
+
+ return {
+ dateError,
+ timeError,
+ };
+ };
+
+ useEffect(() => {
+ if (!data) {
+ return;
+ }
+ validate();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [data]);
+
+ const validateCustomDate = () => validate();
+
+ return {customDateError, customTimeError, validateCustomDate};
+};
+
+function StatusClearAfterPage({currentUserPersonalDetails, customStatus}) {
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+ const clearAfter = lodashGet(currentUserPersonalDetails, 'status.clearAfter', '');
+ const draftClearAfter = lodashGet(customStatus, 'clearAfter', '');
+ const [draftPeriod, setDraftPeriod] = useState(getSelectedStatusType(draftClearAfter || clearAfter));
+ const statusType = useMemo(
+ () =>
+ _.map(CONST.CUSTOM_STATUS_TYPES, (value, key) => ({
+ value,
+ text: translate(`statusPage.timePeriods.${value}`),
+ keyForList: key,
+ isSelected: draftPeriod === value,
+ })),
+ [draftPeriod, translate],
+ );
+
+ const {customDateError, customTimeError, validateCustomDate} = useValidateCustomDate(draftClearAfter);
+
+ const {redBrickDateIndicator, redBrickTimeIndicator} = useMemo(
+ () => ({
+ redBrickDateIndicator: customDateError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : null,
+ redBrickTimeIndicator: customTimeError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : null,
+ }),
+ [customTimeError, customDateError],
+ );
+
+ const onSubmit = () => {
+ const {dateError, timeError} = validateCustomDate();
+ if (dateError || timeError) {
+ return;
+ }
+ let calculatedDraftDate = '';
+ if (draftPeriod === CONST.CUSTOM_STATUS_TYPES.CUSTOM) {
+ calculatedDraftDate = draftClearAfter;
+ } else {
+ const selectedRange = _.find(statusType, (item) => item.isSelected);
+ calculatedDraftDate = DateUtils.getDateFromStatusType(selectedRange.value);
+ }
+ User.updateDraftCustomStatus({clearAfter: calculatedDraftDate});
+ Navigation.goBack(ROUTES.SETTINGS_STATUS);
+ };
+
+ const updateMode = useCallback(
+ (mode) => {
+ if (mode.value === draftPeriod) {
+ return;
+ }
+ setDraftPeriod(mode.value);
+
+ if (mode.value === CONST.CUSTOM_STATUS_TYPES.CUSTOM) {
+ User.updateDraftCustomStatus({clearAfter: DateUtils.getOneHourFromNow()});
+ } else {
+ const selectedRange = _.find(statusType, (item) => item.value === mode.value);
+ const calculatedDraftDate = DateUtils.getDateFromStatusType(selectedRange.value);
+ User.updateDraftCustomStatus({clearAfter: calculatedDraftDate});
+ Navigation.goBack(ROUTES.SETTINGS_STATUS);
+ }
+ },
+ [draftPeriod, statusType],
+ );
+
+ useEffect(() => {
+ User.updateDraftCustomStatus({
+ clearAfter: draftClearAfter || clearAfter,
+ });
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ const customStatusDate = DateUtils.extractDate(draftClearAfter);
+ const customStatusTime = DateUtils.extractTime12Hour(draftClearAfter);
+
+ const timePeriodOptions = useCallback(
+ () =>
+ _.map(statusType, (item, index) => (
+ updateMode(item)}
+ showTooltip={false}
+ />
+ )),
+ [statusType, updateMode],
+ );
+
+ return (
+
+ Navigation.goBack(ROUTES.SETTINGS_STATUS)}
+ />
+ {translate('statusPage.whenClearStatus')}
+
+
+ {timePeriodOptions()}
+ {draftPeriod === CONST.CUSTOM_STATUS_TYPES.CUSTOM && (
+ <>
+ Navigation.navigate(ROUTES.SETTINGS_STATUS_CLEAR_AFTER_DATE)}
+ errorText={customDateError}
+ titleTextStyle={styles.flex1}
+ brickRoadIndicator={redBrickDateIndicator}
+ />
+ Navigation.navigate(ROUTES.SETTINGS_STATUS_CLEAR_AFTER_TIME)}
+ errorText={customTimeError}
+ titleTextStyle={styles.flex1}
+ brickRoadIndicator={redBrickTimeIndicator}
+ />
+ >
+ )}
+
+
+
+ );
+}
+
+StatusClearAfterPage.displayName = 'StatusClearAfterPage';
+StatusClearAfterPage.propTypes = propTypes;
+StatusClearAfterPage.defaultProps = defaultProps;
+
+export default compose(
+ withCurrentUserPersonalDetails,
+ withLocalize,
+ withOnyx({
+ timePeriodType: {
+ key: `${ONYXKEYS.FORMS.SETTINGS_STATUS_SET_CLEAR_AFTER_FORM}Draft`,
+ },
+ clearDateForm: {
+ key: `${ONYXKEYS.FORMS.SETTINGS_STATUS_CLEAR_DATE_FORM}Draft`,
+ },
+ customStatus: {
+ key: ONYXKEYS.CUSTOM_STATUS_DRAFT,
+ },
+ preferredLocale: {
+ key: ONYXKEYS.NVP_PREFERRED_LOCALE,
+ },
+ }),
+)(StatusClearAfterPage);
diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.js b/src/pages/settings/Profile/CustomStatus/StatusPage.js
index 226d0fed8044..bf21d3cd2b54 100644
--- a/src/pages/settings/Profile/CustomStatus/StatusPage.js
+++ b/src/pages/settings/Profile/CustomStatus/StatusPage.js
@@ -1,122 +1,195 @@
import lodashGet from 'lodash/get';
-import React, {useCallback, useEffect, useMemo} from 'react';
-import {View} from 'react-native';
+import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import {InteractionManager, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
-import MobileBackgroundImage from '@assets/images/money-stack.svg';
-import Button from '@components/Button';
+import EmojiPickerButtonDropdown from '@components/EmojiPicker/EmojiPickerButtonDropdown';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
import HeaderPageLayout from '@components/HeaderPageLayout';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
+import TextInput from '@components/TextInput';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
+import DateUtils from '@libs/DateUtils';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as User from '@userActions/User';
+import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
+const INPUT_IDS = {
+ EMOJI_CODE: 'emojiCode',
+ STATUS_TEXT: 'statusText',
+};
+
const propTypes = {
...withCurrentUserPersonalDetailsPropTypes,
};
+const initialEmoji = '💬';
+
function StatusPage({draftStatus, currentUserPersonalDetails}) {
const theme = useTheme();
const styles = useThemeStyles();
+ const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
+ const formRef = useRef(null);
+ const [brickRoadIndicator, setBrickRoadIndicator] = useState('');
const currentUserEmojiCode = lodashGet(currentUserPersonalDetails, 'status.emojiCode', '');
const currentUserStatusText = lodashGet(currentUserPersonalDetails, 'status.text', '');
+ const currentUserClearAfter = lodashGet(currentUserPersonalDetails, 'status.clearAfter', '');
const draftEmojiCode = lodashGet(draftStatus, 'emojiCode');
const draftText = lodashGet(draftStatus, 'text');
+ const draftClearAfter = lodashGet(draftStatus, 'clearAfter');
- const defaultEmoji = draftEmojiCode || currentUserEmojiCode;
- const defaultText = draftEmojiCode ? draftText : currentUserStatusText;
- const hasDraftStatus = !!draftEmojiCode || !!draftText;
- const customStatus = useMemo(() => {
- if (draftEmojiCode) {
- return `${draftEmojiCode} ${draftText}`;
- }
- if (currentUserEmojiCode || currentUserStatusText) {
- return `${currentUserEmojiCode || ''} ${currentUserStatusText || ''}`;
+ const defaultEmoji = draftEmojiCode || currentUserEmojiCode || initialEmoji;
+ const defaultText = draftText || currentUserStatusText;
+
+ const customClearAfter = useMemo(() => {
+ const dataToShow = draftClearAfter || currentUserClearAfter;
+ return DateUtils.getLocalizedTimePeriodDescription(dataToShow);
+ }, [draftClearAfter, currentUserClearAfter]);
+
+ const isValidClearAfterDate = useCallback(() => {
+ const clearAfterTime = draftClearAfter || currentUserClearAfter;
+ if (clearAfterTime === CONST.CUSTOM_STATUS_TYPES.NEVER || clearAfterTime === '') {
+ return true;
}
- return '';
- }, [draftEmojiCode, draftText, currentUserEmojiCode, currentUserStatusText]);
+
+ return DateUtils.isTimeAtLeastOneMinuteInFuture({dateTimeString: clearAfterTime});
+ }, [draftClearAfter, currentUserClearAfter]);
+
+ const navigateBackToPreviousScreen = useCallback(() => Navigation.goBack(ROUTES.SETTINGS_PROFILE, false, true), []);
+ const updateStatus = useCallback(
+ ({emojiCode, statusText}) => {
+ const clearAfterTime = draftClearAfter || currentUserClearAfter;
+ const isValid = DateUtils.isTimeAtLeastOneMinuteInFuture({dateTimeString: clearAfterTime});
+ if (!isValid && clearAfterTime !== CONST.CUSTOM_STATUS_TYPES.NEVER) {
+ setBrickRoadIndicator(isValidClearAfterDate() ? null : CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR);
+ return;
+ }
+
+ User.updateCustomStatus({
+ text: statusText,
+ emojiCode,
+ clearAfter: clearAfterTime !== CONST.CUSTOM_STATUS_TYPES.NEVER ? clearAfterTime : '',
+ });
+
+ User.clearDraftCustomStatus();
+ InteractionManager.runAfterInteractions(() => {
+ navigateBackToPreviousScreen();
+ });
+ },
+ [currentUserClearAfter, draftClearAfter, isValidClearAfterDate, navigateBackToPreviousScreen],
+ );
const clearStatus = () => {
User.clearCustomStatus();
- User.clearDraftCustomStatus();
+ User.updateDraftCustomStatus({
+ text: '',
+ emojiCode: '',
+ clearAfter: DateUtils.getEndOfToday(),
+ });
+ formRef.current.resetForm({[INPUT_IDS.EMOJI_CODE]: initialEmoji});
};
- const navigateBackToSettingsPage = useCallback(() => {
- const topMostReportID = Navigation.getTopmostReportId();
- if (topMostReportID) {
- Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(topMostReportID));
+ useEffect(() => setBrickRoadIndicator(isValidClearAfterDate() ? null : CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR), [isValidClearAfterDate]);
+
+ useEffect(() => {
+ if (!currentUserEmojiCode && !currentUserClearAfter && !draftClearAfter) {
+ User.updateDraftCustomStatus({clearAfter: DateUtils.getEndOfToday()});
} else {
- Navigation.goBack(ROUTES.SETTINGS_PROFILE, false, true);
+ User.updateDraftCustomStatus({clearAfter: currentUserClearAfter});
}
- }, []);
- const updateStatus = useCallback(() => {
- User.updateCustomStatus({text: defaultText, emojiCode: defaultEmoji});
-
- User.clearDraftCustomStatus();
- Navigation.goBack(ROUTES.SETTINGS_PROFILE);
- }, [defaultText, defaultEmoji]);
- const footerComponent = useMemo(
- () =>
- hasDraftStatus ? (
-
- ) : null,
- [hasDraftStatus, translate, updateStatus],
- );
+ return () => User.clearDraftCustomStatus();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
- useEffect(() => () => User.clearDraftCustomStatus(), []);
+ const validateForm = useCallback(() => {
+ if (brickRoadIndicator) {
+ return {clearAfter: ''};
+ }
+ return {};
+ }, [brickRoadIndicator]);
return (
-
- }
- headerContainerStyles={[styles.staticHeaderImage]}
- backgroundColor={theme.PAGE_THEMES[SCREENS.SETTINGS.PROFILE.STATUS].backgroundColor}
- footer={footerComponent}
+
-
- {translate('statusPage.setStatusTitle')}
- {translate('statusPage.statusExplanation')}
-
- Navigation.navigate(ROUTES.SETTINGS_STATUS_SET)}
+
-
- {(!!currentUserEmojiCode || !!currentUserStatusText) && (
-
- )}
-
+
+
+ {translate('statusPage.statusExplanation')}
+
+
+
+
+
+
+ Navigation.navigate(ROUTES.SETTINGS_STATUS_CLEAR_AFTER)}
+ containerStyle={styles.pr2}
+ brickRoadIndicator={brickRoadIndicator}
+ />
+ {(!!currentUserEmojiCode || !!currentUserStatusText) && (
+
+ )}
+
+
+
);
}
diff --git a/src/pages/settings/Profile/CustomStatus/StatusSetPage.js b/src/pages/settings/Profile/CustomStatus/StatusSetPage.js
deleted file mode 100644
index 6c7a2d896aa9..000000000000
--- a/src/pages/settings/Profile/CustomStatus/StatusSetPage.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import lodashGet from 'lodash/get';
-import PropTypes from 'prop-types';
-import React from 'react';
-import {View} from 'react-native';
-import {withOnyx} from 'react-native-onyx';
-import EmojiPickerButtonDropdown from '@components/EmojiPicker/EmojiPickerButtonDropdown';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextInput from '@components/TextInput';
-import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
-import useLocalize from '@hooks/useLocalize';
-import compose from '@libs/compose';
-import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
-import * as User from '@userActions/User';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-
-const propTypes = {
- /** The draft status of the user */
- // eslint-disable-next-line react/require-default-props
- draftStatus: PropTypes.shape({
- /** The emoji code of the draft status */
- emojiCode: PropTypes.string,
- /** The text of the draft status */
- text: PropTypes.string,
- }),
-
- ...withCurrentUserPersonalDetailsPropTypes,
-};
-
-const INPUT_IDS = {
- EMOJI_CODE: 'emojiCode',
- STATUS_TEXT: 'statusText',
-};
-
-function StatusSetPage({draftStatus, currentUserPersonalDetails}) {
- const styles = useThemeStyles();
- const {translate} = useLocalize();
- const defaultEmoji = lodashGet(draftStatus, 'emojiCode') || lodashGet(currentUserPersonalDetails, 'status.emojiCode', '💬');
- const defaultText = lodashGet(draftStatus, 'text') || lodashGet(currentUserPersonalDetails, 'status.text', '');
-
- const onSubmit = (value) => {
- User.updateDraftCustomStatus({text: value.statusText.trim(), emojiCode: value.emojiCode});
- Navigation.goBack(ROUTES.SETTINGS_STATUS);
- };
-
- return (
-
- Navigation.goBack(ROUTES.SETTINGS_STATUS)}
- />
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-StatusSetPage.displayName = 'StatusSetPage';
-StatusSetPage.propTypes = propTypes;
-
-export default compose(
- withCurrentUserPersonalDetails,
- withOnyx({
- draftStatus: {
- key: ONYXKEYS.CUSTOM_STATUS_DRAFT,
- },
- }),
-)(StatusSetPage);
diff --git a/src/pages/settings/Profile/DisplayNamePage.js b/src/pages/settings/Profile/DisplayNamePage.js
index 85f630a41212..8ea471283004 100644
--- a/src/pages/settings/Profile/DisplayNamePage.js
+++ b/src/pages/settings/Profile/DisplayNamePage.js
@@ -12,11 +12,11 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -102,7 +102,7 @@ function DisplayNamePage(props) {
name="fname"
label={props.translate('common.firstName')}
aria-label={props.translate('common.firstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={lodashGet(currentUserDetails, 'firstName', '')}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
spellCheck={false}
@@ -115,7 +115,7 @@ function DisplayNamePage(props) {
name="lname"
label={props.translate('common.lastName')}
aria-label={props.translate('common.lastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={lodashGet(currentUserDetails, 'lastName', '')}
maxLength={CONST.DISPLAY_NAME.MAX_LENGTH}
spellCheck={false}
diff --git a/src/pages/settings/Profile/LoungeAccessPage.js b/src/pages/settings/Profile/LoungeAccessPage.js
index f6b6968372d1..60cb0896a4eb 100644
--- a/src/pages/settings/Profile/LoungeAccessPage.js
+++ b/src/pages/settings/Profile/LoungeAccessPage.js
@@ -5,11 +5,11 @@ import LottieAnimations from '@components/LottieAnimations';
import Text from '@components/Text';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import userPropTypes from '@pages/settings/userPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js
index fa22a3b22f9e..6c883e7fa9d8 100644
--- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js
+++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js
@@ -8,8 +8,8 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
index 10a6d8807afc..393e95cb35fe 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js
@@ -10,10 +10,10 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
index c6ad9f083114..365ea62184ab 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js
@@ -12,11 +12,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -104,7 +104,7 @@ function LegalNamePage(props) {
name="lfname"
label={props.translate('privatePersonalDetails.legalFirstName')}
aria-label={props.translate('privatePersonalDetails.legalFirstName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={legalFirstName}
maxLength={CONST.LEGAL_NAME.MAX_LENGTH + CONST.SEARCH_MAX_LENGTH}
spellCheck={false}
@@ -117,7 +117,7 @@ function LegalNamePage(props) {
name="llname"
label={props.translate('privatePersonalDetails.legalLastName')}
aria-label={props.translate('privatePersonalDetails.legalLastName')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
defaultValue={legalLastName}
maxLength={CONST.LEGAL_NAME.MAX_LENGTH + CONST.SEARCH_MAX_LENGTH}
spellCheck={false}
diff --git a/src/pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage.js b/src/pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage.js
index 4fc2bbb17428..cf6887b7e04c 100644
--- a/src/pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage.js
+++ b/src/pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage.js
@@ -11,10 +11,10 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js
index fc6c38f96335..89dfa4f0e419 100755
--- a/src/pages/settings/Profile/ProfilePage.js
+++ b/src/pages/settings/Profile/ProfilePage.js
@@ -13,11 +13,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as UserUtils from '@libs/UserUtils';
import userPropTypes from '@pages/settings/userPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as App from '@userActions/App';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js
index 40f2562724ef..20022f22523a 100644
--- a/src/pages/settings/Profile/PronounsPage.js
+++ b/src/pages/settings/Profile/PronounsPage.js
@@ -10,9 +10,9 @@ import SelectionList from '@components/SelectionList';
import Text from '@components/Text';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Profile/TimezoneInitialPage.js b/src/pages/settings/Profile/TimezoneInitialPage.js
index 463b20029745..bf86e8a5a077 100644
--- a/src/pages/settings/Profile/TimezoneInitialPage.js
+++ b/src/pages/settings/Profile/TimezoneInitialPage.js
@@ -8,9 +8,9 @@ import Switch from '@components/Switch';
import Text from '@components/Text';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PersonalDetails from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Report/ReportSettingsPage.js b/src/pages/settings/Report/ReportSettingsPage.js
index 0676f0875932..c7cfd9c7850d 100644
--- a/src/pages/settings/Report/ReportSettingsPage.js
+++ b/src/pages/settings/Report/ReportSettingsPage.js
@@ -14,13 +14,13 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import {getGroupChatName} from '@libs/GroupChatUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import withReportOrNotFound from '@pages/home/report/withReportOrNotFound';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js
index 7916043c7e20..fa2bee325e8a 100644
--- a/src/pages/settings/Report/RoomNamePage.js
+++ b/src/pages/settings/Report/RoomNamePage.js
@@ -9,6 +9,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import RoomNameInput from '@components/RoomNameInput';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
@@ -16,7 +17,6 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import withReportOrNotFound from '@pages/home/report/withReportOrNotFound';
import reportPropTypes from '@pages/reportPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Security/CloseAccountPage.js b/src/pages/settings/Security/CloseAccountPage.js
index 8c1b851ee176..9aad345d7b3d 100644
--- a/src/pages/settings/Security/CloseAccountPage.js
+++ b/src/pages/settings/Security/CloseAccountPage.js
@@ -12,10 +12,10 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as CloseAccount from '@userActions/CloseAccount';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
@@ -109,7 +109,7 @@ function CloseAccountPage(props) {
autoGrowHeight
label={props.translate('closeAccountPage.enterMessageHere')}
aria-label={props.translate('closeAccountPage.enterMessageHere')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt5, styles.autoGrowHeightMultilineInput]}
/>
@@ -121,7 +121,7 @@ function CloseAccountPage(props) {
autoCapitalize="none"
label={props.translate('closeAccountPage.enterDefaultContact')}
aria-label={props.translate('closeAccountPage.enterDefaultContact')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt5]}
autoCorrect={false}
inputMode={Str.isValidEmail(userEmailOrPhone) ? CONST.INPUT_MODE.EMAIL : CONST.INPUT_MODE.TEXT}
diff --git a/src/pages/settings/Security/SecuritySettingsPage.js b/src/pages/settings/Security/SecuritySettingsPage.js
index 95a0efa2fc39..392a264977c6 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.js
+++ b/src/pages/settings/Security/SecuritySettingsPage.js
@@ -8,11 +8,11 @@ import IllustratedHeaderPageLayout from '@components/IllustratedHeaderPageLayout
import LottieAnimations from '@components/LottieAnimations';
import MenuItemList from '@components/MenuItemList';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
diff --git a/src/pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper.js b/src/pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper.js
index 69d662ba6e81..ba899a0e2d20 100644
--- a/src/pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper.js
+++ b/src/pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper.js
@@ -4,7 +4,7 @@ import useAnimatedStepContext from '@components/AnimatedStep/useAnimatedStepCont
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
import StepWrapperPropTypes from './StepWrapperPropTypes';
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.js
index 86d218ec63ae..420d976dcd26 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.js
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.js
@@ -11,14 +11,14 @@ import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayTo
import Section from '@components/Section';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import Clipboard from '@libs/Clipboard';
import localFileDownload from '@libs/localFileDownload';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
import {defaultAccount, TwoFactorAuthPropTypes} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthPropTypes';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/DisabledStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/DisabledStep.js
index 9de25ecb8f4b..db64a805d088 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/DisabledStep.js
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/DisabledStep.js
@@ -4,8 +4,8 @@ import Button from '@components/Button';
import FixedFooter from '@components/FixedFooter';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.js
index e0f90c57f350..27f9c0f04404 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.js
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.js
@@ -5,10 +5,10 @@ import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import Section from '@components/Section';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
index 8a2b4c6fdf6c..e5f809204bd6 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/VerifyStep.js
@@ -11,12 +11,12 @@ import QRCode from '@components/QRCode';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import Clipboard from '@libs/Clipboard';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
import TwoFactorAuthForm from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm';
import {defaultAccount, TwoFactorAuthPropTypes} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js b/src/pages/settings/Wallet/ActivatePhysicalCardPage.js
index 788c571d9e7d..bfc8583998b6 100644
--- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js
+++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.js
@@ -12,14 +12,14 @@ import MagicCodeInput from '@components/MagicCodeInput';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as CardUtils from '@libs/CardUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as CardSettings from '@userActions/Card';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Wallet/AddDebitCardPage.js b/src/pages/settings/Wallet/AddDebitCardPage.js
index 872052067213..0704bf6bf3b8 100644
--- a/src/pages/settings/Wallet/AddDebitCardPage.js
+++ b/src/pages/settings/Wallet/AddDebitCardPage.js
@@ -14,9 +14,9 @@ import TextInput from '@components/TextInput';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -122,7 +122,7 @@ function DebitCardPage(props) {
inputID="nameOnCard"
label={translate('addDebitCardPage.nameOnCard')}
aria-label={translate('addDebitCardPage.nameOnCard')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={nameOnCardRef}
spellCheck={false}
/>
@@ -131,7 +131,7 @@ function DebitCardPage(props) {
inputID="cardNumber"
label={translate('addDebitCardPage.debitCardNumber')}
aria-label={translate('addDebitCardPage.debitCardNumber')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
containerStyles={[styles.mt4]}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
@@ -142,7 +142,7 @@ function DebitCardPage(props) {
inputID="expirationDate"
label={translate('addDebitCardPage.expiration')}
aria-label={translate('addDebitCardPage.expiration')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
placeholder={translate('addDebitCardPage.expirationDate')}
inputMode={CONST.INPUT_MODE.NUMERIC}
maxLength={4}
@@ -154,7 +154,7 @@ function DebitCardPage(props) {
inputID="securityCode"
label={translate('addDebitCardPage.cvv')}
aria-label={translate('addDebitCardPage.cvv')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
maxLength={4}
inputMode={CONST.INPUT_MODE.NUMERIC}
/>
@@ -176,7 +176,7 @@ function DebitCardPage(props) {
inputID="addressZipCode"
label={translate('common.zip')}
aria-label={translate('common.zip')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputMode={CONST.INPUT_MODE.NUMERIC}
maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE}
hint={translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})}
diff --git a/src/pages/settings/Wallet/Card/BaseGetPhysicalCard.js b/src/pages/settings/Wallet/Card/BaseGetPhysicalCard.js
index 4176393e92dd..1d1ce906189b 100644
--- a/src/pages/settings/Wallet/Card/BaseGetPhysicalCard.js
+++ b/src/pages/settings/Wallet/Card/BaseGetPhysicalCard.js
@@ -6,6 +6,7 @@ import _ from 'underscore';
import Form from '@components/Form';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as FormActions from '@libs/actions/FormActions';
import * as Wallet from '@libs/actions/Wallet';
import * as CardUtils from '@libs/CardUtils';
@@ -13,7 +14,6 @@ import FormUtils from '@libs/FormUtils';
import * as GetPhysicalCardUtils from '@libs/GetPhysicalCardUtils';
import Navigation from '@libs/Navigation/Navigation';
import assignedCardPropTypes from '@pages/settings/Wallet/assignedCardPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.js b/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.js
index 0ae83cd28b5c..9f364c32c075 100644
--- a/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.js
+++ b/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.js
@@ -5,10 +5,10 @@ import * as Expensicons from '@components/Icon/Expensicons';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import FormUtils from '@libs/FormUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardName.js b/src/pages/settings/Wallet/Card/GetPhysicalCardName.js
index 3c87bed424ba..0040dac8b75f 100644
--- a/src/pages/settings/Wallet/Card/GetPhysicalCardName.js
+++ b/src/pages/settings/Wallet/Card/GetPhysicalCardName.js
@@ -4,9 +4,9 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import FormUtils from '@libs/FormUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js
index 82b684332491..3d4c7f4ac6fb 100644
--- a/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js
+++ b/src/pages/settings/Wallet/Card/GetPhysicalCardPhone.js
@@ -6,8 +6,8 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import TextInput from '@components/TextInput';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import FormUtils from '@libs/FormUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.js b/src/pages/settings/Wallet/ChooseTransferAccountPage.js
index 2ffbf12f52c2..815d2e883cf0 100644
--- a/src/pages/settings/Wallet/ChooseTransferAccountPage.js
+++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.js
@@ -6,9 +6,9 @@ import * as Expensicons from '@components/Icon/Expensicons';
import MenuItem from '@components/MenuItem';
import ScreenWrapper from '@components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Wallet/DangerCardSection.js b/src/pages/settings/Wallet/DangerCardSection.js
deleted file mode 100644
index 91add21b75ea..000000000000
--- a/src/pages/settings/Wallet/DangerCardSection.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import {View} from 'react-native';
-import * as Illustrations from '@components/Icon/Illustrations';
-import Text from '@components/Text';
-import useThemeStyles from '@styles/useThemeStyles';
-
-const propTypes = {
- title: PropTypes.string.isRequired,
- description: PropTypes.string.isRequired,
-};
-
-function DangerCardSection({title, description}) {
- const styles = useThemeStyles();
- return (
-
-
-
- {title}
- {description}
-
-
-
-
-
-
- );
-}
-
-DangerCardSection.propTypes = propTypes;
-DangerCardSection.displayName = 'DangerCardSection';
-
-export default DangerCardSection;
diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.js b/src/pages/settings/Wallet/ExpensifyCardPage.js
index e92fca171817..513da42b9011 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage.js
+++ b/src/pages/settings/Wallet/ExpensifyCardPage.js
@@ -13,21 +13,20 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import FormUtils from '@libs/FormUtils';
import * as GetPhysicalCardUtils from '@libs/GetPhysicalCardUtils';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Card from '@userActions/Card';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import assignedCardPropTypes from './assignedCardPropTypes';
-import DangerCardSection from './DangerCardSection';
+import RedDotCardSection from './RedDotCardSection';
import CardDetails from './WalletPage/CardDetails';
const propTypes = {
@@ -123,7 +122,6 @@ function ExpensifyCardPage({
params: {domain},
},
}) {
- const theme = useTheme();
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const {translate} = useLocalize();
@@ -184,8 +182,8 @@ function ExpensifyCardPage({
{hasDetectedDomainFraud ? (
@@ -193,17 +191,15 @@ function ExpensifyCardPage({
{hasDetectedIndividualFraud && !hasDetectedDomainFraud ? (
<>
-
- Link.openOldDotLink('inbox')}
/>
>
diff --git a/src/pages/settings/Wallet/PaymentMethodList.js b/src/pages/settings/Wallet/PaymentMethodList.js
index 4f6d0331f3b4..6e424a918b7e 100644
--- a/src/pages/settings/Wallet/PaymentMethodList.js
+++ b/src/pages/settings/Wallet/PaymentMethodList.js
@@ -16,13 +16,13 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import * as PaymentUtils from '@libs/PaymentUtils';
import stylePropTypes from '@styles/stylePropTypes';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Wallet/RedDotCardSection.js b/src/pages/settings/Wallet/RedDotCardSection.js
new file mode 100644
index 000000000000..7025cf7bf1a2
--- /dev/null
+++ b/src/pages/settings/Wallet/RedDotCardSection.js
@@ -0,0 +1,40 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import {View} from 'react-native';
+import Icon from '@components/Icon';
+import * as Expensicons from '@components/Icon/Expensicons';
+import Text from '@components/Text';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+
+const propTypes = {
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string.isRequired,
+};
+
+function RedDotCardSection({title, description}) {
+ const theme = useTheme();
+ const styles = useThemeStyles();
+
+ return (
+
+
+
+
+
+
+ {title}
+ {description}
+
+
+
+ );
+}
+
+RedDotCardSection.propTypes = propTypes;
+RedDotCardSection.displayName = 'RedDotCardSection';
+
+export default RedDotCardSection;
diff --git a/src/pages/settings/Wallet/ReportCardLostPage.js b/src/pages/settings/Wallet/ReportCardLostPage.js
index aa313b73a6bd..b01dc99cb485 100644
--- a/src/pages/settings/Wallet/ReportCardLostPage.js
+++ b/src/pages/settings/Wallet/ReportCardLostPage.js
@@ -12,11 +12,11 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import useThemeStyles from '@styles/useThemeStyles';
import * as CardActions from '@userActions/Card';
import * as FormActions from '@userActions/FormActions';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js
index 01d3c272ad8b..fa88e01d8b41 100644
--- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js
+++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js
@@ -9,11 +9,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Card from '@userActions/Card';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/TransferBalancePage.js b/src/pages/settings/Wallet/TransferBalancePage.js
index 2414edb29087..303baa4b4b13 100644
--- a/src/pages/settings/Wallet/TransferBalancePage.js
+++ b/src/pages/settings/Wallet/TransferBalancePage.js
@@ -15,12 +15,12 @@ import {withNetwork} from '@components/OnyxProvider';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as PaymentUtils from '@libs/PaymentUtils';
import userWalletPropTypes from '@pages/EnablePayments/userWalletPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as PaymentMethods from '@userActions/PaymentMethods';
import CONST from '@src/CONST';
diff --git a/src/pages/settings/Wallet/WalletEmptyState.js b/src/pages/settings/Wallet/WalletEmptyState.js
index f4609bdc8534..7a3a9e9ce6b7 100644
--- a/src/pages/settings/Wallet/WalletEmptyState.js
+++ b/src/pages/settings/Wallet/WalletEmptyState.js
@@ -6,8 +6,8 @@ import * as Illustrations from '@components/Icon/Illustrations';
import IllustratedHeaderPageLayout from '@components/IllustratedHeaderPageLayout';
import LottieAnimations from '@components/LottieAnimations';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
import Navigation from '@libs/Navigation/Navigation';
-import useTheme from '@styles/themes/useTheme';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.js b/src/pages/settings/Wallet/WalletPage/CardDetails.js
index a51c4c5fad6f..b51c34e89d17 100644
--- a/src/pages/settings/Wallet/WalletPage/CardDetails.js
+++ b/src/pages/settings/Wallet/WalletPage/CardDetails.js
@@ -8,10 +8,10 @@ import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayTo
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails';
+import useThemeStyles from '@hooks/useThemeStyles';
import Clipboard from '@libs/Clipboard';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index 6f452eed3629..e0577930b73d 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -1,11 +1,11 @@
import lodashGet from 'lodash/get';
import React, {useCallback, useEffect, useRef, useState} from 'react';
-import {ActivityIndicator, InteractionManager, ScrollView, View} from 'react-native';
+import {ActivityIndicator, ScrollView, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu';
import Button from '@components/Button';
-import ConfirmContent from '@components/ConfirmContent';
+import ConfirmModal from '@components/ConfirmModal';
import CurrentWalletBalance from '@components/CurrentWalletBalance';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Icon from '@components/Icon';
@@ -20,6 +20,8 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import WalletSection from '@components/WalletSection';
import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import getClickedTargetLocation from '@libs/getClickedTargetLocation';
@@ -27,8 +29,6 @@ import Navigation from '@libs/Navigation/Navigation';
import * as PaymentUtils from '@libs/PaymentUtils';
import PaymentMethodList from '@pages/settings/Wallet/PaymentMethodList';
import WalletEmptyState from '@pages/settings/Wallet/WalletEmptyState';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as BankAccounts from '@userActions/BankAccounts';
import * as PaymentMethods from '@userActions/PaymentMethods';
@@ -62,7 +62,7 @@ function WalletPage({bankAccountList, cardList, fundList, isLoadingPaymentMethod
anchorPositionTop: 0,
anchorPositionRight: 0,
});
- const [showConfirmDeleteContent, setShowConfirmDeleteContent] = useState(false);
+ const [showConfirmDeleteModal, setShowConfirmDeleteModal] = useState(false);
const hasBankAccount = !_.isEmpty(bankAccountList) || !_.isEmpty(fundList);
const hasWallet = !_.isEmpty(userWallet);
@@ -215,10 +215,8 @@ function WalletPage({bankAccountList, cardList, fundList, isLoadingPaymentMethod
*/
const hideDefaultDeleteMenu = useCallback(() => {
setShouldShowDefaultDeleteMenu(false);
- InteractionManager.runAfterInteractions(() => {
- setShowConfirmDeleteContent(false);
- });
- }, [setShouldShowDefaultDeleteMenu, setShowConfirmDeleteContent]);
+ setShowConfirmDeleteModal(false);
+ }, [setShouldShowDefaultDeleteMenu, setShowConfirmDeleteModal]);
const makeDefaultPaymentMethod = useCallback(() => {
const paymentCardList = fundList || {};
@@ -487,11 +485,9 @@ function WalletPage({bankAccountList, cardList, fundList, isLoadingPaymentMethod
top: anchorPosition.anchorPositionTop,
right: anchorPosition.anchorPositionRight,
}}
- withoutOverlay
anchorRef={paymentMethodButtonRef}
- onModalHide={resetSelectedPaymentMethodData}
>
- {!showConfirmDeleteContent ? (
+ {!showConfirmDeleteModal && (
{isPopoverBottomMount && (
)}
{
- setShowConfirmDeleteContent(true);
- }}
+ onPress={() => setShowConfirmDeleteModal(true)}
style={[shouldShowMakeDefaultButton ? styles.mt4 : {}]}
text={translate('common.delete')}
danger
/>
- ) : (
- {
- deletePaymentMethod();
- hideDefaultDeleteMenu();
- }}
- onCancel={hideDefaultDeleteMenu}
- contentStyles={!isSmallScreenWidth ? [styles.sidebarPopover, styles.willChangeTransform] : undefined}
- title={translate('walletPage.deleteAccount')}
- prompt={translate('walletPage.deleteConfirmation')}
- confirmText={translate('common.delete')}
- cancelText={translate('common.cancel')}
- anchorPosition={{
- top: anchorPosition.anchorPositionTop,
- right: anchorPosition.anchorPositionRight,
- }}
- shouldShowCancelButton
- danger
- />
)}
+ {
+ deletePaymentMethod();
+ hideDefaultDeleteMenu();
+ }}
+ onCancel={hideDefaultDeleteMenu}
+ title={translate('walletPage.deleteAccount')}
+ prompt={translate('walletPage.deleteConfirmation')}
+ confirmText={translate('common.delete')}
+ cancelText={translate('common.cancel')}
+ shouldShowCancelButton
+ danger
+ onModalHide={resetSelectedPaymentMethodData}
+ />
)}
diff --git a/src/pages/signin/ChangeExpensifyLoginLink.js b/src/pages/signin/ChangeExpensifyLoginLink.js
index 219085240459..6ba9b7fcd0f5 100755
--- a/src/pages/signin/ChangeExpensifyLoginLink.js
+++ b/src/pages/signin/ChangeExpensifyLoginLink.js
@@ -6,8 +6,8 @@ import _ from 'underscore';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -38,7 +38,7 @@ function ChangeExpensifyLoginLink(props) {
diff --git a/src/pages/signin/ChooseSSOOrMagicCode.js b/src/pages/signin/ChooseSSOOrMagicCode.js
index bfb704b71f6d..db985e525545 100644
--- a/src/pages/signin/ChooseSSOOrMagicCode.js
+++ b/src/pages/signin/ChooseSSOOrMagicCode.js
@@ -8,10 +8,10 @@ import FormHelpMessage from '@components/FormHelpMessage';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/signin/EmailDeliveryFailurePage.js b/src/pages/signin/EmailDeliveryFailurePage.js
index fe39618e79df..9996374cc6cd 100644
--- a/src/pages/signin/EmailDeliveryFailurePage.js
+++ b/src/pages/signin/EmailDeliveryFailurePage.js
@@ -8,7 +8,7 @@ import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useKeyboardState from '@hooks/useKeyboardState';
import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import redirectToSignIn from '@userActions/SignInRedirect';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/signin/Licenses.js b/src/pages/signin/Licenses.js
index ef9cd8548a2d..605cfed328b5 100644
--- a/src/pages/signin/Licenses.js
+++ b/src/pages/signin/Licenses.js
@@ -4,7 +4,7 @@ import LocalePicker from '@components/LocalePicker';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
const currentYear = new Date().getFullYear();
diff --git a/src/pages/signin/LoginForm/BaseLoginForm.js b/src/pages/signin/LoginForm/BaseLoginForm.js
index e7ac249582a9..81c2e985f8da 100644
--- a/src/pages/signin/LoginForm/BaseLoginForm.js
+++ b/src/pages/signin/LoginForm/BaseLoginForm.js
@@ -18,6 +18,7 @@ import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withToggleVisibilityView from '@components/withToggleVisibilityView';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
@@ -27,7 +28,6 @@ import * as LoginUtils from '@libs/LoginUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import Visibility from '@libs/Visibility';
-import useThemeStyles from '@styles/useThemeStyles';
import * as CloseAccount from '@userActions/CloseAccount';
import * as MemoryOnlyKeys from '@userActions/MemoryOnlyKeys/MemoryOnlyKeys';
import * as Session from '@userActions/Session';
diff --git a/src/pages/signin/SignInHeroCopy.js b/src/pages/signin/SignInHeroCopy.js
index 75c53c6b2344..847de3868cee 100644
--- a/src/pages/signin/SignInHeroCopy.js
+++ b/src/pages/signin/SignInHeroCopy.js
@@ -4,9 +4,9 @@ import {View} from 'react-native';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/pages/signin/SignInHeroImage.js b/src/pages/signin/SignInHeroImage.js
index 302e09a7afbc..c665a09932c2 100644
--- a/src/pages/signin/SignInHeroImage.js
+++ b/src/pages/signin/SignInHeroImage.js
@@ -3,7 +3,7 @@ import React from 'react';
import Lottie from '@components/Lottie';
import LottieAnimations from '@components/LottieAnimations';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/pages/signin/SignInModal.js b/src/pages/signin/SignInModal.js
index 9784eb0b67a1..1bb8b6065a15 100644
--- a/src/pages/signin/SignInModal.js
+++ b/src/pages/signin/SignInModal.js
@@ -1,8 +1,8 @@
import React from 'react';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
+import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import SignInPage from './SignInPage';
diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js
index dbad6324c922..23c5b09a0909 100644
--- a/src/pages/signin/SignInPage.js
+++ b/src/pages/signin/SignInPage.js
@@ -6,18 +6,18 @@ import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import CustomStatusBar from '@components/CustomStatusBar';
+import ThemeProvider from '@components/ThemeProvider';
+import ThemeStylesProvider from '@components/ThemeStylesProvider';
import useLocalize from '@hooks/useLocalize';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as ActiveClientManager from '@libs/ActiveClientManager';
import * as Localize from '@libs/Localize';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import Performance from '@libs/Performance';
-import ThemeProvider from '@styles/themes/ThemeProvider';
-import ThemeStylesProvider from '@styles/ThemeStylesProvider';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as App from '@userActions/App';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/signin/SignInPageHero.js b/src/pages/signin/SignInPageHero.js
index a7bc13785764..81415452451e 100644
--- a/src/pages/signin/SignInPageHero.js
+++ b/src/pages/signin/SignInPageHero.js
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import SignInHeroCopy from './SignInHeroCopy';
import SignInHeroImage from './SignInHeroImage';
diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js
index 4185bba88149..b6d9e82726f0 100644
--- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js
+++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.android.js
@@ -1,6 +1,6 @@
import React from 'react';
import AndroidBackgroundImage from '@assets/images/home-background--android.svg';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import defaultPropTypes from './propTypes';
function BackgroundImage(props) {
diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.js
index 872ce7139317..ac93ceeb4e2c 100644
--- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.js
+++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.js
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import DesktopBackgroundImage from '@assets/images/home-background--desktop.svg';
import MobileBackgroundImage from '@assets/images/home-background--mobile.svg';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import defaultPropTypes from './propTypes';
const defaultProps = {
diff --git a/src/pages/signin/SignInPageLayout/Footer.js b/src/pages/signin/SignInPageLayout/Footer.js
index 261f0473a6e5..3837914a79bd 100644
--- a/src/pages/signin/SignInPageLayout/Footer.js
+++ b/src/pages/signin/SignInPageLayout/Footer.js
@@ -8,11 +8,11 @@ import * as Expensicons from '@components/Icon/Expensicons';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import Licenses from '@pages/signin/Licenses';
import Socials from '@pages/signin/Socials';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
diff --git a/src/pages/signin/SignInPageLayout/SignInPageContent.js b/src/pages/signin/SignInPageLayout/SignInPageContent.js
index fd48ebecf066..5865c235335a 100755
--- a/src/pages/signin/SignInPageLayout/SignInPageContent.js
+++ b/src/pages/signin/SignInPageLayout/SignInPageContent.js
@@ -7,11 +7,11 @@ import OfflineIndicator from '@components/OfflineIndicator';
import SignInPageForm from '@components/SignInPageForm';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import SignInHeroImage from '@pages/signin/SignInHeroImage';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
const propTypes = {
diff --git a/src/pages/signin/SignInPageLayout/index.js b/src/pages/signin/SignInPageLayout/index.js
index 667f873c572e..bc171dd1dc12 100644
--- a/src/pages/signin/SignInPageLayout/index.js
+++ b/src/pages/signin/SignInPageLayout/index.js
@@ -5,12 +5,12 @@ import {withSafeAreaInsets} from 'react-native-safe-area-context';
import SignInGradient from '@assets/images/home-fade-gradient.svg';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrevious from '@hooks/usePrevious';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import SignInPageHero from '@pages/signin/SignInPageHero';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
import BackgroundImage from './BackgroundImage';
import Footer from './Footer';
diff --git a/src/pages/signin/Socials.js b/src/pages/signin/Socials.js
index f5cbbd81e2d8..a5747402d16e 100644
--- a/src/pages/signin/Socials.js
+++ b/src/pages/signin/Socials.js
@@ -4,8 +4,8 @@ import _ from 'underscore';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
-import useTheme from '@styles/themes/useTheme';
-import useThemeStyles from '@styles/useThemeStyles';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
diff --git a/src/pages/signin/Terms.js b/src/pages/signin/Terms.js
index 44e024208fc8..75db2e5debd1 100644
--- a/src/pages/signin/Terms.js
+++ b/src/pages/signin/Terms.js
@@ -2,7 +2,7 @@ import React, {useMemo} from 'react';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
-import useThemeStyles from '@styles/useThemeStyles';
+import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
function Terms(props) {
diff --git a/src/pages/signin/ThirdPartySignInPage.js b/src/pages/signin/ThirdPartySignInPage.js
index f0d0f8d42e93..35297e22e665 100644
--- a/src/pages/signin/ThirdPartySignInPage.js
+++ b/src/pages/signin/ThirdPartySignInPage.js
@@ -9,9 +9,9 @@ import Text from '@components/Text';
import TextLink from '@components/TextLink';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/signin/UnlinkLoginForm.js b/src/pages/signin/UnlinkLoginForm.js
index 1ae9b1fd79c6..851a984407e1 100644
--- a/src/pages/signin/UnlinkLoginForm.js
+++ b/src/pages/signin/UnlinkLoginForm.js
@@ -11,8 +11,8 @@ import {withNetwork} from '@components/OnyxProvider';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import redirectToSignIn from '@userActions/SignInRedirect';
import CONST from '@src/CONST';
diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
index 3104042bf33b..03db6d3436cf 100755
--- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
+++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js
@@ -14,15 +14,15 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import usePrevious from '@hooks/usePrevious';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import ChangeExpensifyLoginLink from '@pages/signin/ChangeExpensifyLoginLink';
import Terms from '@pages/signin/Terms';
-import useTheme from '@styles/themes/useTheme';
-import useStyleUtils from '@styles/useStyleUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Session from '@userActions/Session';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
@@ -340,7 +340,7 @@ function BaseValidateCodeForm(props) {
hoverDimmingValue={1}
pressDimmingValue={0.2}
disabled={isValidateCodeFormSubmitting}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.isUsingRecoveryCode ? props.translate('recoveryCodeForm.use2fa') : props.translate('recoveryCodeForm.useRecoveryCode')}
>
{props.isUsingRecoveryCode ? props.translate('recoveryCodeForm.use2fa') : props.translate('recoveryCodeForm.useRecoveryCode')}
@@ -376,7 +376,7 @@ function BaseValidateCodeForm(props) {
disabled={shouldDisableResendValidateCode}
hoverDimmingValue={1}
pressDimmingValue={0.2}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
accessibilityLabel={props.translate('validateCodeForm.magicCodeNotReceived')}
>
diff --git a/src/pages/tasks/NewTaskDescriptionPage.js b/src/pages/tasks/NewTaskDescriptionPage.js
index b9a569646148..b11e7c163755 100644
--- a/src/pages/tasks/NewTaskDescriptionPage.js
+++ b/src/pages/tasks/NewTaskDescriptionPage.js
@@ -10,11 +10,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import updateMultilineInputRange from '@libs/updateMultilineInputRange';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -73,7 +73,7 @@ function NewTaskDescriptionPage(props) {
inputID="taskDescription"
label={props.translate('newTaskPage.descriptionOptional')}
accessibilityLabel={props.translate('newTaskPage.descriptionOptional')}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
ref={(el) => {
inputCallbackRef(el);
updateMultilineInputRange(el);
diff --git a/src/pages/tasks/NewTaskDetailsPage.js b/src/pages/tasks/NewTaskDetailsPage.js
index 94cb804a39e1..3dab58dfad04 100644
--- a/src/pages/tasks/NewTaskDetailsPage.js
+++ b/src/pages/tasks/NewTaskDetailsPage.js
@@ -10,11 +10,11 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -94,7 +94,7 @@ function NewTaskDetailsPage(props) {
openEditor(policy.id)))}
accessibilityLabel={translate('workspace.common.settings')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
openEditor(policy.id)))}
accessibilityLabel={translate('workspace.common.settings')}
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
+ role={CONST.ROLE.BUTTON}
>
(this.welcomeMessageInputRef = el)}
- role={CONST.ACCESSIBILITY_ROLE.TEXT}
+ role={CONST.ROLE.PRESENTATION}
inputID="welcomeMessage"
label={this.props.translate('workspace.inviteMessage.personalMessagePrompt')}
accessibilityLabel={this.props.translate('workspace.inviteMessage.personalMessagePrompt')}
diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js
index 3528224f39b9..7a28558ee587 100644
--- a/src/pages/workspace/WorkspaceInvitePage.js
+++ b/src/pages/workspace/WorkspaceInvitePage.js
@@ -11,12 +11,12 @@ import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js
index 59993087c44c..9834d4e9e1c0 100644
--- a/src/pages/workspace/WorkspaceMembersPage.js
+++ b/src/pages/workspace/WorkspaceMembersPage.js
@@ -19,6 +19,7 @@ import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultPro
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import compose from '@libs/compose';
import Log from '@libs/Log';
@@ -28,7 +29,6 @@ import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as UserUtils from '@libs/UserUtils';
import personalDetailsPropType from '@pages/personalDetailsPropType';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js
index 7ddd78621d2d..04464652632f 100644
--- a/src/pages/workspace/WorkspaceNewRoomPage.js
+++ b/src/pages/workspace/WorkspaceNewRoomPage.js
@@ -3,8 +3,11 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
+import BlockingView from '@components/BlockingViews/BlockingView';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
+import Button from '@components/Button';
import Form from '@components/Form';
+import * as Illustrations from '@components/Icon/Illustrations';
import KeyboardAvoidingView from '@components/KeyboardAvoidingView';
import OfflineIndicator from '@components/OfflineIndicator';
import RoomNameInput from '@components/RoomNameInput';
@@ -17,6 +20,7 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import compose from '@libs/compose';
import * as ErrorUtils from '@libs/ErrorUtils';
@@ -25,12 +29,11 @@ import Permissions from '@libs/Permissions';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import variables from '@styles/variables';
-import * as App from '@userActions/App';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
const propTypes = {
/** All reports shared with the user */
@@ -216,13 +219,28 @@ function WorkspaceNewRoomPage(props) {
const {inputCallbackRef} = useAutoFocusInput();
+ const renderEmptyWorkspaceView = () => (
+ <>
+
+ Navigation.navigate(ROUTES.SETTINGS_WORKSPACES)}
+ style={[styles.mh5, styles.mb5]}
+ />
+ {isSmallScreenWidth && }
+ >
+ );
+
return (
- App.createWorkspaceWithPolicyDraftAndNavigateToIt()}
- >
+
- {({insets}) => (
-
-
+ {isSmallScreenWidth && }
+
+ )
+ }
);
diff --git a/src/pages/workspace/WorkspacePageWithSections.js b/src/pages/workspace/WorkspacePageWithSections.js
index bea94ed3ef4e..6b5c179a2e51 100644
--- a/src/pages/workspace/WorkspacePageWithSections.js
+++ b/src/pages/workspace/WorkspacePageWithSections.js
@@ -9,13 +9,13 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollViewWithContext from '@components/ScrollViewWithContext';
import useNetwork from '@hooks/useNetwork';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import BankAccount from '@libs/models/BankAccount';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes';
import userPropTypes from '@pages/settings/userPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
diff --git a/src/pages/workspace/WorkspaceResetBankAccountModal.js b/src/pages/workspace/WorkspaceResetBankAccountModal.js
index 19e15a2828bc..f4ad662ebb75 100644
--- a/src/pages/workspace/WorkspaceResetBankAccountModal.js
+++ b/src/pages/workspace/WorkspaceResetBankAccountModal.js
@@ -5,9 +5,9 @@ import {withOnyx} from 'react-native-onyx';
import ConfirmModal from '@components/ConfirmModal';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import BankAccount from '@libs/models/BankAccount';
import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes';
-import useThemeStyles from '@styles/useThemeStyles';
import * as BankAccounts from '@userActions/BankAccounts';
import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.js
index b51146cde7f3..9bc4b755fce9 100644
--- a/src/pages/workspace/WorkspaceSettingsPage.js
+++ b/src/pages/workspace/WorkspaceSettingsPage.js
@@ -16,12 +16,12 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions';
import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
import compose from '@libs/compose';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
-import useThemeStyles from '@styles/useThemeStyles';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -143,7 +143,7 @@ function WorkspaceSettingsPage({policy, currencyList, windowWidth, route}) {
;
- policyMembers: OnyxEntry;
+ policyMembers: OnyxEntry;
policyDraft: OnyxEntry;
policyMembersDraft: OnyxEntry;
};
diff --git a/src/stories/CheckboxWithLabel.stories.js b/src/stories/CheckboxWithLabel.stories.js
index e8d45f434b16..2da4713e81b3 100644
--- a/src/stories/CheckboxWithLabel.stories.js
+++ b/src/stories/CheckboxWithLabel.stories.js
@@ -1,7 +1,7 @@
import React from 'react';
import CheckboxWithLabel from '@components/CheckboxWithLabel';
import Text from '@components/Text';
-import styles from '@styles/styles';
+import {defaultStyles} from '@styles/index';
/**
* We use the Component Story Format for writing stories. Follow the docs here:
@@ -34,9 +34,9 @@ WithLabelComponent.args = {
onInputChange: () => {},
LabelComponent: () => (
<>
- Test
- Test
- Test
+ Test
+ Test
+ Test
>
),
};
diff --git a/src/stories/Composer.stories.js b/src/stories/Composer.stories.js
index 799012e1c051..04fa9be7de86 100644
--- a/src/stories/Composer.stories.js
+++ b/src/stories/Composer.stories.js
@@ -5,9 +5,9 @@ import Composer from '@components/Composer';
import RenderHTML from '@components/RenderHTML';
import Text from '@components/Text';
import withNavigationFallback from '@components/withNavigationFallback';
-import styles from '@styles/styles';
-import themeColors from '@styles/themes/default';
-import useStyleUtils from '@styles/useStyleUtils';
+import useStyleUtils from '@hooks/useStyleUtils';
+import {defaultStyles} from '@styles/index';
+import {defaultTheme} from '@styles/theme';
import CONST from '@src/CONST';
const ComposerWithNavigation = withNavigationFallback(Composer);
@@ -32,29 +32,29 @@ function Default(args) {
return (
-
+
-
+
- Entered Comment (Drop Enabled)
+ Entered Comment (Drop Enabled){comment}
-
- Rendered Comment
+
+ Rendered Comment
{Boolean(renderedHTML) && }
{Boolean(pastedFile) && (
-
+
-
+
{fileURL ? (
-
+ Release to upload file
diff --git a/src/stories/Form.stories.js b/src/stories/Form.stories.js
index 6473b1074f17..a937c6732e9b 100644
--- a/src/stories/Form.stories.js
+++ b/src/stories/Form.stories.js
@@ -11,7 +11,7 @@ import Text from '@components/Text';
import TextInput from '@components/TextInput';
import NetworkConnection from '@libs/NetworkConnection';
import * as ValidationUtils from '@libs/ValidationUtils';
-import styles from '@styles/styles';
+import {defaultStyles} from '@styles/index';
import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
@@ -47,7 +47,7 @@ function Template(args) {
-
+ I accept the Expensify Terms of Service}
/>
@@ -153,7 +153,7 @@ function WithNativeEventHandler(args) {
- Admin
+
+ Admin
),
};
@@ -290,8 +290,8 @@ function WithSectionHeader(args) {
accountID: item.keyForList,
login: item.text,
rightElement: isAdmin && (
-
- Admin
+
+ Admin
),
};
@@ -350,8 +350,8 @@ function WithConfirmButton(args) {
accountID: item.keyForList,
login: item.text,
rightElement: isAdmin && (
-
- Admin
+
+ Admin
),
};
diff --git a/src/styles/illustrations/ThemeIllustrationsContext.ts b/src/styles/illustrations/ThemeIllustrationsContext.ts
deleted file mode 100644
index e4956e6c0479..000000000000
--- a/src/styles/illustrations/ThemeIllustrationsContext.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-import DarkIllustrations from './dark';
-import {Illustrations} from './types';
-
-const ThemeIllustrationsContext = React.createContext(DarkIllustrations);
-
-export default ThemeIllustrationsContext;
diff --git a/src/styles/styles.ts b/src/styles/index.ts
similarity index 97%
rename from src/styles/styles.ts
rename to src/styles/index.ts
index b51c22f7766c..9e02335bde0d 100644
--- a/src/styles/styles.ts
+++ b/src/styles/index.ts
@@ -2,42 +2,43 @@
import {LineLayerStyleProps} from '@rnmapbox/maps/src/utils/MapboxStyles';
import lodashClamp from 'lodash/clamp';
import {LineLayer} from 'react-map-gl';
-import {AnimatableNumericValue, Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native';
+import {AnimatableNumericValue, Animated, ImageStyle, StyleSheet, TextStyle, ViewStyle} from 'react-native';
import {CustomAnimation} from 'react-native-animatable';
import {PickerStyle} from 'react-native-picker-select';
import {MixedStyleDeclaration, MixedStyleRecord} from 'react-native-render-html';
import DotLottieAnimation from '@components/LottieAnimations/types';
import * as Browser from '@libs/Browser';
import CONST from '@src/CONST';
-import addOutlineWidth from './addOutlineWidth';
-import codeStyles from './codeStyles';
-import colors from './colors';
-import fontFamily from './fontFamily';
-import fontWeightBold from './fontWeight/bold';
-import getPopOverVerticalOffset from './getPopOverVerticalOffset';
-import optionAlternateTextPlatformStyles from './optionAlternateTextPlatformStyles';
-import overflowXHidden from './overflowXHidden';
-import pointerEventsAuto from './pointerEventsAuto';
-import pointerEventsBoxNone from './pointerEventsBoxNone';
-import pointerEventsNone from './pointerEventsNone';
-import {defaultTheme} from './themes/themes';
-import {type ThemeColors} from './themes/types';
-import borders from './utilities/borders';
-import cursor from './utilities/cursor';
-import display from './utilities/display';
-import flex from './utilities/flex';
-import objectFit from './utilities/objectFit';
-import overflow from './utilities/overflow';
-import positioning from './utilities/positioning';
-import sizing from './utilities/sizing';
-import spacing from './utilities/spacing';
-import textDecorationLine from './utilities/textDecorationLine';
-import textUnderline from './utilities/textUnderline';
-import userSelect from './utilities/userSelect';
-import visibility from './utilities/visibility';
-import whiteSpace from './utilities/whiteSpace';
-import wordBreak from './utilities/wordBreak';
-import writingDirection from './utilities/writingDirection';
+import {defaultTheme} from './theme';
+import colors from './theme/colors';
+import {type ThemeColors} from './theme/types';
+import addOutlineWidth from './utils/addOutlineWidth';
+import borders from './utils/borders';
+import codeStyles from './utils/codeStyles';
+import cursor from './utils/cursor';
+import display from './utils/display';
+import editedLabelStyles from './utils/editedLabelStyles';
+import flex from './utils/flex';
+import fontFamily from './utils/fontFamily';
+import fontWeightBold from './utils/fontWeight/bold';
+import getPopOverVerticalOffset from './utils/getPopOverVerticalOffset';
+import objectFit from './utils/objectFit';
+import optionAlternateTextPlatformStyles from './utils/optionAlternateTextPlatformStyles';
+import overflow from './utils/overflow';
+import overflowXHidden from './utils/overflowXHidden';
+import pointerEventsAuto from './utils/pointerEventsAuto';
+import pointerEventsBoxNone from './utils/pointerEventsBoxNone';
+import pointerEventsNone from './utils/pointerEventsNone';
+import positioning from './utils/positioning';
+import sizing from './utils/sizing';
+import spacing from './utils/spacing';
+import textDecorationLine from './utils/textDecorationLine';
+import textUnderline from './utils/textUnderline';
+import userSelect from './utils/userSelect';
+import visibility from './utils/visibility';
+import whiteSpace from './utils/whiteSpace';
+import wordBreak from './utils/wordBreak';
+import writingDirection from './utils/writingDirection';
import variables from './variables';
type ColorScheme = (typeof CONST.COLOR_SCHEME)[keyof typeof CONST.COLOR_SCHEME];
@@ -234,6 +235,7 @@ const styles = (theme: ThemeColors) =>
...textUnderline,
...objectFit,
...textDecorationLine,
+ editedLabelStyles,
autoCompleteSuggestionsContainer: {
backgroundColor: theme.appBG,
@@ -2422,6 +2424,11 @@ const styles = (theme: ThemeColors) =>
alignItems: 'center',
padding: 20,
},
+ numberPadWrapper: {
+ width: '100%',
+ alignItems: 'center',
+ paddingHorizontal: 20,
+ },
avatarSectionWrapper: {
width: '100%',
@@ -3677,7 +3684,6 @@ const styles = (theme: ThemeColors) =>
alignItems: 'center',
paddingLeft: 10,
paddingRight: 4,
- marginBottom: 32,
alignSelf: 'flex-start',
...userSelect.userSelectNone,
},
@@ -3897,10 +3903,59 @@ const styles = (theme: ThemeColors) =>
fontSize: variables.fontSizeNormal,
marginRight: 4,
},
+ timePickerInput: {
+ fontSize: 69,
+ minWidth: 56,
+ alignSelf: 'center',
+ },
+ timePickerWidth100: {
+ width: 100,
+ },
+ timePickerHeight100: {
+ height: 100,
+ },
+ timePickerSemiDot: {
+ fontSize: 69,
+ height: 84,
+ alignSelf: 'center',
+ },
+ timePickerSwitcherContainer: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ },
+ selectionListRadioSeparator: {
+ height: StyleSheet.hairlineWidth,
+ backgroundColor: theme.border,
+ marginHorizontal: 20,
+ },
+
draggableTopBar: {
height: 30,
width: '100%',
},
+ menuItemError: {
+ position: 'absolute',
+ bottom: -4,
+ left: 20,
+ right: 20,
+ },
+ formHelperMessage: {
+ height: 32,
+ },
+ timePickerInputExtraSmall: {
+ fontSize: 50,
+ },
+ setTimeFormButtonContainer: {
+ minHeight: 54,
+ },
+ timePickerInputsContainer: {
+ maxHeight: 100,
+ },
+ timePickerButtonErrorText: {
+ position: 'absolute',
+ top: -36,
+ },
chatBottomLoader: {
position: 'absolute',
@@ -3945,7 +4000,7 @@ const styles = (theme: ThemeColors) =>
left: 16,
bottom: 16,
width: variables.cardNameWidth,
- color: theme.text,
+ color: theme.textLight,
fontSize: variables.fontSizeSmall,
lineHeight: variables.lineHeightLarge,
},
@@ -3957,23 +4012,15 @@ const styles = (theme: ThemeColors) =>
paddingBottom: 0,
},
- walletDangerSection: {
- backgroundColor: theme.dangerSection,
- color: theme.dangerSection,
- borderRadius: variables.componentBorderRadiusCard,
- width: 'auto',
- marginHorizontal: 20,
- marginBottom: 6,
- },
-
- walletDangerSectionTitle: {
- fontSize: variables.fontSizeNormal,
- fontFamily: fontFamily.EXP_NEUE_BOLD,
+ walletRedDotSectionTitle: {
+ color: theme.text,
fontWeight: fontWeightBold,
+ fontSize: variables.fontSizeNormal,
lineHeight: variables.lineHeightXLarge,
},
- walletDangerSectionText: {
+ walletRedDotSectionText: {
+ color: theme.darkSupportingText,
fontSize: variables.fontSizeLabel,
lineHeight: variables.lineHeightNormal,
},
@@ -4006,4 +4053,5 @@ type ThemeStyles = ReturnType;
const defaultStyles = styles(defaultTheme);
export default styles;
-export {defaultStyles, type Styles, type ThemeStyles, type StatusBarStyle, type ColorScheme};
+export {defaultStyles};
+export type {Styles, ThemeStyles, StatusBarStyle, ColorScheme};
diff --git a/src/styles/stylePropTypes.js b/src/styles/stylePropTypes.js
index b97decba621c..f9ecdb98ff13 100644
--- a/src/styles/stylePropTypes.js
+++ b/src/styles/stylePropTypes.js
@@ -1,3 +1,5 @@
import PropTypes from 'prop-types';
-export default PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object), PropTypes.func]);
+const stylePropTypes = PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object), PropTypes.func]);
+
+export default stylePropTypes;
diff --git a/src/styles/colors.ts b/src/styles/theme/colors.ts
similarity index 98%
rename from src/styles/colors.ts
rename to src/styles/theme/colors.ts
index 35d93f060c86..061336d2d114 100644
--- a/src/styles/colors.ts
+++ b/src/styles/theme/colors.ts
@@ -1,4 +1,4 @@
-import {Color} from './themes/types';
+import {Color} from './types';
/**
* DO NOT import colors.js into files. Use the theme switching hooks and HOCs instead.
diff --git a/src/styles/themes/ThemeContext.ts b/src/styles/theme/context/ThemeContext.ts
similarity index 59%
rename from src/styles/themes/ThemeContext.ts
rename to src/styles/theme/context/ThemeContext.ts
index ec35675953fe..64cd805b3f59 100644
--- a/src/styles/themes/ThemeContext.ts
+++ b/src/styles/theme/context/ThemeContext.ts
@@ -1,6 +1,6 @@
import React from 'react';
-import {defaultTheme} from './themes';
-import {type ThemeColors} from './types';
+import {type ThemeColors} from '@styles/theme/types';
+import {defaultTheme} from '..';
const ThemeContext = React.createContext(defaultTheme);
diff --git a/src/styles/theme/context/ThemeIllustrationsContext.ts b/src/styles/theme/context/ThemeIllustrationsContext.ts
new file mode 100644
index 000000000000..b70cf6aa5ea2
--- /dev/null
+++ b/src/styles/theme/context/ThemeIllustrationsContext.ts
@@ -0,0 +1,7 @@
+import React from 'react';
+import {DefaultIllustrations} from '@styles/theme/illustrations';
+import {IllustrationsType} from '@styles/theme/illustrations/types';
+
+const ThemeIllustrationsContext = React.createContext(DefaultIllustrations);
+
+export default ThemeIllustrationsContext;
diff --git a/src/styles/ThemeStylesContext.ts b/src/styles/theme/context/ThemeStylesContext.ts
similarity index 62%
rename from src/styles/ThemeStylesContext.ts
rename to src/styles/theme/context/ThemeStylesContext.ts
index 73f044f2dcbd..a1c81bbd9c7c 100644
--- a/src/styles/ThemeStylesContext.ts
+++ b/src/styles/theme/context/ThemeStylesContext.ts
@@ -1,8 +1,8 @@
import React from 'react';
-import {defaultStyles} from './styles';
-import type {ThemeStyles} from './styles';
-import {DefaultStyleUtils} from './utils';
-import type {StyleUtilsType} from './utils';
+import {defaultStyles} from '@styles/index';
+import type {ThemeStyles} from '@styles/index';
+import {DefaultStyleUtils} from '@styles/utils';
+import type {StyleUtilsType} from '@styles/utils';
type ThemeStylesContextType = {
styles: ThemeStyles;
diff --git a/src/styles/theme/illustrations/index.ts b/src/styles/theme/illustrations/index.ts
new file mode 100644
index 000000000000..9526dbcd1023
--- /dev/null
+++ b/src/styles/theme/illustrations/index.ts
@@ -0,0 +1,15 @@
+import {ThemePreferenceWithoutSystem} from '@styles/theme/types';
+import CONST from '@src/CONST';
+import darkIllustrations from './themes/dark';
+import lightIllustrations from './themes/light';
+import type {IllustrationsType} from './types';
+
+const Illustrations = {
+ [CONST.THEME.LIGHT]: lightIllustrations,
+ [CONST.THEME.DARK]: darkIllustrations,
+} satisfies Record;
+
+const DefaultIllustrations = Illustrations[CONST.THEME.FALLBACK];
+
+export default Illustrations;
+export {DefaultIllustrations};
diff --git a/src/styles/illustrations/dark.ts b/src/styles/theme/illustrations/themes/dark.ts
similarity index 80%
rename from src/styles/illustrations/dark.ts
rename to src/styles/theme/illustrations/themes/dark.ts
index ca52a24a4e4e..2a4390ae2520 100644
--- a/src/styles/illustrations/dark.ts
+++ b/src/styles/theme/illustrations/themes/dark.ts
@@ -1,12 +1,12 @@
import EmptyStateBackgroundImage from '@assets/images/themeDependent/empty-state_background-fade-dark.png';
import ExampleCheckEN from '@assets/images/themeDependent/example-check-image-dark-en.png';
import ExampleCheckES from '@assets/images/themeDependent/example-check-image-dark-es.png';
-import {Illustrations} from './types';
+import {IllustrationsType} from '@styles/theme/illustrations/types';
const illustrations = {
EmptyStateBackgroundImage,
ExampleCheckEN,
ExampleCheckES,
-} satisfies Illustrations;
+} satisfies IllustrationsType;
export default illustrations;
diff --git a/src/styles/illustrations/light.ts b/src/styles/theme/illustrations/themes/light.ts
similarity index 80%
rename from src/styles/illustrations/light.ts
rename to src/styles/theme/illustrations/themes/light.ts
index a953a312327f..f41114a04efa 100644
--- a/src/styles/illustrations/light.ts
+++ b/src/styles/theme/illustrations/themes/light.ts
@@ -1,12 +1,12 @@
import EmptyStateBackgroundImage from '@assets/images/themeDependent/empty-state_background-fade-light.png';
import ExampleCheckEN from '@assets/images/themeDependent/example-check-image-light-en.png';
import ExampleCheckES from '@assets/images/themeDependent/example-check-image-light-es.png';
-import {Illustrations} from './types';
+import {IllustrationsType} from '@styles/theme/illustrations/types';
const illustrations = {
EmptyStateBackgroundImage,
ExampleCheckEN,
ExampleCheckES,
-} satisfies Illustrations;
+} satisfies IllustrationsType;
export default illustrations;
diff --git a/src/styles/illustrations/types.ts b/src/styles/theme/illustrations/types.ts
similarity index 80%
rename from src/styles/illustrations/types.ts
rename to src/styles/theme/illustrations/types.ts
index bfb1db4a19c1..bda98dc55fbf 100644
--- a/src/styles/illustrations/types.ts
+++ b/src/styles/theme/illustrations/types.ts
@@ -1,10 +1,10 @@
import {ImageSourcePropType} from 'react-native';
-type Illustrations = {
+type IllustrationsType = {
EmptyStateBackgroundImage: ImageSourcePropType;
ExampleCheckES: ImageSourcePropType;
ExampleCheckEN: ImageSourcePropType;
};
// eslint-disable-next-line import/prefer-default-export
-export {type Illustrations};
+export {type IllustrationsType};
diff --git a/src/styles/themes/themes.ts b/src/styles/theme/index.ts
similarity index 69%
rename from src/styles/themes/themes.ts
rename to src/styles/theme/index.ts
index c0a305df294f..c8c3a6ec12c1 100644
--- a/src/styles/themes/themes.ts
+++ b/src/styles/theme/index.ts
@@ -1,6 +1,6 @@
import CONST from '@src/CONST';
-import darkTheme from './default';
-import lightTheme from './light';
+import darkTheme from './themes/dark';
+import lightTheme from './themes/light';
import {type ThemeColors, ThemePreferenceWithoutSystem} from './types';
const themes = {
@@ -8,7 +8,7 @@ const themes = {
[CONST.THEME.DARK]: darkTheme,
} satisfies Record;
-const defaultTheme = themes[CONST.THEME.DEFAULT];
+const defaultTheme = themes[CONST.THEME.FALLBACK];
export default themes;
export {defaultTheme};
diff --git a/src/styles/themes/default.ts b/src/styles/theme/themes/dark.ts
similarity index 93%
rename from src/styles/themes/default.ts
rename to src/styles/theme/themes/dark.ts
index ee930b4a2a04..714802095810 100644
--- a/src/styles/themes/default.ts
+++ b/src/styles/theme/themes/dark.ts
@@ -1,7 +1,7 @@
-import colors from '@styles/colors';
+import colors from '@styles/theme/colors';
+import {type ThemeColors} from '@styles/theme/types';
import CONST from '@src/CONST';
import SCREENS from '@src/SCREENS';
-import {type ThemeColors} from './types';
const darkTheme = {
// Figma keys
@@ -34,7 +34,7 @@ const darkTheme = {
successPressed: colors.greenPressed,
transparent: colors.transparent,
signInPage: colors.green800,
- dangerSection: colors.tangerine800,
+ darkSupportingText: colors.productDark800,
// Additional keys
overlay: colors.productDark400,
@@ -120,13 +120,17 @@ const darkTheme = {
statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT,
},
[SCREENS.SETTINGS.PROFILE.STATUS]: {
- backgroundColor: colors.green700,
+ backgroundColor: colors.darkAppBackground,
statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
},
[SCREENS.SETTINGS.ROOT]: {
backgroundColor: colors.productDark200,
statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
},
+ [SCREENS.RIGHT_MODAL.REFERRAL]: {
+ backgroundColor: colors.pink800,
+ statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
+ },
},
statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
diff --git a/src/styles/themes/light.ts b/src/styles/theme/themes/light.ts
similarity index 94%
rename from src/styles/themes/light.ts
rename to src/styles/theme/themes/light.ts
index 0e4ca1c8a879..8d401f7533d7 100644
--- a/src/styles/themes/light.ts
+++ b/src/styles/theme/themes/light.ts
@@ -1,7 +1,7 @@
-import colors from '@styles/colors';
+import colors from '@styles/theme/colors';
+import {type ThemeColors} from '@styles/theme/types';
import CONST from '@src/CONST';
import SCREENS from '@src/SCREENS';
-import {type ThemeColors} from './types';
const lightTheme = {
// Figma keys
@@ -34,7 +34,7 @@ const lightTheme = {
successPressed: colors.greenPressed,
transparent: colors.transparent,
signInPage: colors.green800,
- dangerSection: colors.tangerine800,
+ darkSupportingText: colors.productDark800,
// Additional keys
overlay: colors.productLight400,
@@ -127,6 +127,10 @@ const lightTheme = {
backgroundColor: colors.productLight200,
statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT,
},
+ [SCREENS.RIGHT_MODAL.REFERRAL]: {
+ backgroundColor: colors.pink800,
+ statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT,
+ },
},
statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT,
diff --git a/src/styles/themes/types.ts b/src/styles/theme/types.ts
similarity index 93%
rename from src/styles/themes/types.ts
rename to src/styles/theme/types.ts
index c674b6057d0f..56da65ddd17d 100644
--- a/src/styles/themes/types.ts
+++ b/src/styles/theme/types.ts
@@ -1,10 +1,10 @@
-import {type ColorScheme, type StatusBarStyle} from '@styles/styles';
import CONST from '@src/CONST';
+import {type ColorScheme, type StatusBarStyle} from '..';
type Color = string;
type ThemePreference = (typeof CONST.THEME)[keyof typeof CONST.THEME];
-type ThemePreferenceWithoutSystem = Exclude;
+type ThemePreferenceWithoutSystem = Exclude;
type ThemeColors = {
// Figma keys
@@ -37,7 +37,7 @@ type ThemeColors = {
successPressed: Color;
transparent: Color;
signInPage: Color;
- dangerSection: Color;
+ darkSupportingText: Color;
// Additional keys
overlay: Color;
diff --git a/src/styles/addOutlineWidth/index.native.ts b/src/styles/utils/addOutlineWidth/index.native.ts
similarity index 100%
rename from src/styles/addOutlineWidth/index.native.ts
rename to src/styles/utils/addOutlineWidth/index.native.ts
diff --git a/src/styles/addOutlineWidth/index.ts b/src/styles/utils/addOutlineWidth/index.ts
similarity index 100%
rename from src/styles/addOutlineWidth/index.ts
rename to src/styles/utils/addOutlineWidth/index.ts
diff --git a/src/styles/addOutlineWidth/types.ts b/src/styles/utils/addOutlineWidth/types.ts
similarity index 76%
rename from src/styles/addOutlineWidth/types.ts
rename to src/styles/utils/addOutlineWidth/types.ts
index 91e3f7409259..f6b9be63893c 100644
--- a/src/styles/addOutlineWidth/types.ts
+++ b/src/styles/utils/addOutlineWidth/types.ts
@@ -1,5 +1,5 @@
import {TextStyle} from 'react-native';
-import {type ThemeColors} from '@styles/themes/types';
+import {type ThemeColors} from '@styles/theme/types';
type AddOutlineWidth = (theme: ThemeColors, obj: TextStyle, val?: number, hasError?: boolean) => TextStyle;
diff --git a/src/styles/utilities/borders.ts b/src/styles/utils/borders.ts
similarity index 100%
rename from src/styles/utilities/borders.ts
rename to src/styles/utils/borders.ts
diff --git a/src/styles/cardStyles/index.native.ts b/src/styles/utils/cardStyles/index.native.ts
similarity index 100%
rename from src/styles/cardStyles/index.native.ts
rename to src/styles/utils/cardStyles/index.native.ts
diff --git a/src/styles/cardStyles/index.ts b/src/styles/utils/cardStyles/index.ts
similarity index 81%
rename from src/styles/cardStyles/index.ts
rename to src/styles/utils/cardStyles/index.ts
index b5d3c069b73a..77a00695d20a 100644
--- a/src/styles/cardStyles/index.ts
+++ b/src/styles/utils/cardStyles/index.ts
@@ -1,4 +1,4 @@
-import positioning from '@styles/utilities/positioning';
+import positioning from '@styles/utils/positioning';
import GetCardStyles from './types';
/**
diff --git a/src/styles/cardStyles/types.ts b/src/styles/utils/cardStyles/types.ts
similarity index 100%
rename from src/styles/cardStyles/types.ts
rename to src/styles/utils/cardStyles/types.ts
diff --git a/src/styles/codeStyles/index.android.ts b/src/styles/utils/codeStyles/index.android.ts
similarity index 100%
rename from src/styles/codeStyles/index.android.ts
rename to src/styles/utils/codeStyles/index.android.ts
diff --git a/src/styles/codeStyles/index.ios.ts b/src/styles/utils/codeStyles/index.ios.ts
similarity index 100%
rename from src/styles/codeStyles/index.ios.ts
rename to src/styles/utils/codeStyles/index.ios.ts
diff --git a/src/styles/codeStyles/index.ts b/src/styles/utils/codeStyles/index.ts
similarity index 100%
rename from src/styles/codeStyles/index.ts
rename to src/styles/utils/codeStyles/index.ts
diff --git a/src/styles/codeStyles/types.ts b/src/styles/utils/codeStyles/types.ts
similarity index 85%
rename from src/styles/codeStyles/types.ts
rename to src/styles/utils/codeStyles/types.ts
index 25e35f492089..f223d980e67b 100644
--- a/src/styles/codeStyles/types.ts
+++ b/src/styles/utils/codeStyles/types.ts
@@ -1,7 +1,7 @@
import {TextStyle, ViewStyle} from 'react-native';
type CodeWordWrapperStyles = ViewStyle;
-type CodeWordStyles = TextStyle;
+type CodeWordStyles = ViewStyle;
type CodeTextStyles = TextStyle;
export type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles};
diff --git a/src/styles/containerComposeStyles/index.native.ts b/src/styles/utils/containerComposeStyles/index.native.ts
similarity index 100%
rename from src/styles/containerComposeStyles/index.native.ts
rename to src/styles/utils/containerComposeStyles/index.native.ts
diff --git a/src/styles/containerComposeStyles/index.ts b/src/styles/utils/containerComposeStyles/index.ts
similarity index 100%
rename from src/styles/containerComposeStyles/index.ts
rename to src/styles/utils/containerComposeStyles/index.ts
diff --git a/src/styles/containerComposeStyles/types.ts b/src/styles/utils/containerComposeStyles/types.ts
similarity index 75%
rename from src/styles/containerComposeStyles/types.ts
rename to src/styles/utils/containerComposeStyles/types.ts
index 9930e0230016..2b2d23b7f8c1 100644
--- a/src/styles/containerComposeStyles/types.ts
+++ b/src/styles/utils/containerComposeStyles/types.ts
@@ -1,5 +1,5 @@
import {ViewStyle} from 'react-native';
-import {type ThemeStyles} from '@styles/styles';
+import {type ThemeStyles} from '@styles/index';
type ContainerComposeStyles = (styles: ThemeStyles) => ViewStyle[];
diff --git a/src/styles/utilities/cursor/index.native.ts b/src/styles/utils/cursor/index.native.ts
similarity index 100%
rename from src/styles/utilities/cursor/index.native.ts
rename to src/styles/utils/cursor/index.native.ts
diff --git a/src/styles/utilities/cursor/index.ts b/src/styles/utils/cursor/index.ts
similarity index 100%
rename from src/styles/utilities/cursor/index.ts
rename to src/styles/utils/cursor/index.ts
diff --git a/src/styles/utilities/cursor/types.ts b/src/styles/utils/cursor/types.ts
similarity index 100%
rename from src/styles/utilities/cursor/types.ts
rename to src/styles/utils/cursor/types.ts
diff --git a/src/styles/utilities/display.ts b/src/styles/utils/display.ts
similarity index 100%
rename from src/styles/utilities/display.ts
rename to src/styles/utils/display.ts
diff --git a/src/styles/editedLabelStyles/index.native.ts b/src/styles/utils/editedLabelStyles/index.native.ts
similarity index 100%
rename from src/styles/editedLabelStyles/index.native.ts
rename to src/styles/utils/editedLabelStyles/index.native.ts
diff --git a/src/styles/editedLabelStyles/index.ts b/src/styles/utils/editedLabelStyles/index.ts
similarity index 67%
rename from src/styles/editedLabelStyles/index.ts
rename to src/styles/utils/editedLabelStyles/index.ts
index 339c50d8a4df..427918af1202 100644
--- a/src/styles/editedLabelStyles/index.ts
+++ b/src/styles/utils/editedLabelStyles/index.ts
@@ -1,5 +1,5 @@
-import display from '@styles/utilities/display';
-import flex from '@styles/utilities/flex';
+import display from '@styles/utils/display';
+import flex from '@styles/utils/flex';
import EditedLabelStyles from './types';
const editedLabelStyles: EditedLabelStyles = {
diff --git a/src/styles/editedLabelStyles/types.ts b/src/styles/utils/editedLabelStyles/types.ts
similarity index 100%
rename from src/styles/editedLabelStyles/types.ts
rename to src/styles/utils/editedLabelStyles/types.ts
diff --git a/src/styles/utilities/flex.ts b/src/styles/utils/flex.ts
similarity index 100%
rename from src/styles/utilities/flex.ts
rename to src/styles/utils/flex.ts
diff --git a/src/styles/fontFamily/bold/index.android.ts b/src/styles/utils/fontFamily/bold/index.android.ts
similarity index 100%
rename from src/styles/fontFamily/bold/index.android.ts
rename to src/styles/utils/fontFamily/bold/index.android.ts
diff --git a/src/styles/fontFamily/bold/index.ios.ts b/src/styles/utils/fontFamily/bold/index.ios.ts
similarity index 100%
rename from src/styles/fontFamily/bold/index.ios.ts
rename to src/styles/utils/fontFamily/bold/index.ios.ts
diff --git a/src/styles/fontFamily/bold/index.ts b/src/styles/utils/fontFamily/bold/index.ts
similarity index 100%
rename from src/styles/fontFamily/bold/index.ts
rename to src/styles/utils/fontFamily/bold/index.ts
diff --git a/src/styles/fontFamily/bold/types.ts b/src/styles/utils/fontFamily/bold/types.ts
similarity index 100%
rename from src/styles/fontFamily/bold/types.ts
rename to src/styles/utils/fontFamily/bold/types.ts
diff --git a/src/styles/fontFamily/index.native.ts b/src/styles/utils/fontFamily/index.native.ts
similarity index 100%
rename from src/styles/fontFamily/index.native.ts
rename to src/styles/utils/fontFamily/index.native.ts
diff --git a/src/styles/fontFamily/index.ts b/src/styles/utils/fontFamily/index.ts
similarity index 100%
rename from src/styles/fontFamily/index.ts
rename to src/styles/utils/fontFamily/index.ts
diff --git a/src/styles/fontFamily/multiFontFamily.ts b/src/styles/utils/fontFamily/multiFontFamily.ts
similarity index 100%
rename from src/styles/fontFamily/multiFontFamily.ts
rename to src/styles/utils/fontFamily/multiFontFamily.ts
diff --git a/src/styles/fontFamily/singleFontFamily.ts b/src/styles/utils/fontFamily/singleFontFamily.ts
similarity index 100%
rename from src/styles/fontFamily/singleFontFamily.ts
rename to src/styles/utils/fontFamily/singleFontFamily.ts
diff --git a/src/styles/fontFamily/types.ts b/src/styles/utils/fontFamily/types.ts
similarity index 100%
rename from src/styles/fontFamily/types.ts
rename to src/styles/utils/fontFamily/types.ts
diff --git a/src/styles/fontWeight/bold/index.android.ts b/src/styles/utils/fontWeight/bold/index.android.ts
similarity index 100%
rename from src/styles/fontWeight/bold/index.android.ts
rename to src/styles/utils/fontWeight/bold/index.android.ts
diff --git a/src/styles/fontWeight/bold/index.ts b/src/styles/utils/fontWeight/bold/index.ts
similarity index 100%
rename from src/styles/fontWeight/bold/index.ts
rename to src/styles/utils/fontWeight/bold/index.ts
diff --git a/src/styles/fontWeight/bold/types.ts b/src/styles/utils/fontWeight/bold/types.ts
similarity index 100%
rename from src/styles/fontWeight/bold/types.ts
rename to src/styles/utils/fontWeight/bold/types.ts
diff --git a/src/styles/utils/ModalStyleUtils.ts b/src/styles/utils/generators/ModalStyleUtils.ts
similarity index 95%
rename from src/styles/utils/ModalStyleUtils.ts
rename to src/styles/utils/generators/ModalStyleUtils.ts
index cf312a4e76f7..67faec504d61 100644
--- a/src/styles/utils/ModalStyleUtils.ts
+++ b/src/styles/utils/generators/ModalStyleUtils.ts
@@ -1,10 +1,10 @@
import {ViewStyle} from 'react-native';
import {ModalProps} from 'react-native-modal';
import {ValueOf} from 'type-fest';
-import {type ThemeStyles} from '@styles/styles';
-import {type ThemeColors} from '@styles/themes/types';
+import {ThemeStyles} from '@styles/index';
import variables from '@styles/variables';
import CONST from '@src/CONST';
+import StyleUtilGenerator from './types';
function getCenteredModalStyles(styles: ThemeStyles, windowWidth: number, isSmallScreenWidth: boolean, isFullScreenWhenSmall = false): ViewStyle {
const modalStyles = styles.centeredModalStyles(isSmallScreenWidth, isFullScreenWhenSmall);
@@ -36,14 +36,18 @@ type GetModalStyles = {
shouldAddTopSafeAreaPadding: boolean;
};
-const createModalStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
+type GetModalStylesStyleUtil = {
getModalStyles: (
type: ModalType | undefined,
windowDimensions: WindowDimensions,
- popoverAnchorPosition: ViewStyle = {},
- innerContainerStyle: ViewStyle = {},
- outerStyle: ViewStyle = {},
- ): GetModalStyles => {
+ popoverAnchorPosition?: ViewStyle,
+ innerContainerStyle?: ViewStyle,
+ outerStyle?: ViewStyle,
+ ) => GetModalStyles;
+};
+
+const createModalStyleUtils: StyleUtilGenerator = ({theme, styles}) => ({
+ getModalStyles: (type, windowDimensions, popoverAnchorPosition = {}, innerContainerStyle = {}, outerStyle = {}): GetModalStyles => {
const {isSmallScreenWidth, windowWidth} = windowDimensions;
let modalStyle: GetModalStyles['modalStyle'] = {
diff --git a/src/styles/utils/ReportActionContextMenuStyleUtils.ts b/src/styles/utils/generators/ReportActionContextMenuStyleUtils.ts
similarity index 73%
rename from src/styles/utils/ReportActionContextMenuStyleUtils.ts
rename to src/styles/utils/generators/ReportActionContextMenuStyleUtils.ts
index 9dd3c2a0d203..10904fca05cd 100644
--- a/src/styles/utils/ReportActionContextMenuStyleUtils.ts
+++ b/src/styles/utils/generators/ReportActionContextMenuStyleUtils.ts
@@ -1,7 +1,8 @@
import {ViewStyle} from 'react-native';
-import {type ThemeStyles} from '@styles/styles';
-import {type ThemeColors} from '@styles/themes/types';
+import {ThemeStyles} from '@styles/index';
+import {type ThemeColors} from '@styles/theme/types';
import variables from '@styles/variables';
+import StyleUtilGenerator from './types';
const getDefaultWrapperStyle = (theme: ThemeColors): ViewStyle => ({
backgroundColor: theme.componentBG,
@@ -20,6 +21,8 @@ const getMiniWrapperStyle = (theme: ThemeColors, styles: ThemeStyles): ViewStyle
},
];
+type GetReportActionContextMenuStylesStyleUtil = {getReportActionContextMenuStyles: (isMini: boolean, isSmallScreenWidth: boolean) => ViewStyle[]};
+
/**
* Generate the wrapper styles for the ReportActionContextMenu.
*
@@ -27,8 +30,8 @@ const getMiniWrapperStyle = (theme: ThemeColors, styles: ThemeStyles): ViewStyle
* @param isSmallScreenWidth
* @param theme
*/
-const createReportActionContextMenuStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
- getReportActionContextMenuStyles: (isMini: boolean, isSmallScreenWidth: boolean): ViewStyle[] => {
+const createReportActionContextMenuStyleUtils: StyleUtilGenerator = ({theme, styles}) => ({
+ getReportActionContextMenuStyles: (isMini, isSmallScreenWidth) => {
if (isMini) {
return getMiniWrapperStyle(theme, styles);
}
diff --git a/src/styles/utils/TooltipStyleUtils.ts b/src/styles/utils/generators/TooltipStyleUtils.ts
similarity index 96%
rename from src/styles/utils/TooltipStyleUtils.ts
rename to src/styles/utils/generators/TooltipStyleUtils.ts
index 5c12a27ee981..0e9fda1a3388 100644
--- a/src/styles/utils/TooltipStyleUtils.ts
+++ b/src/styles/utils/generators/TooltipStyleUtils.ts
@@ -1,11 +1,10 @@
import {Animated, TextStyle, View, ViewStyle} from 'react-native';
-import fontFamily from '@styles/fontFamily';
-import {type ThemeStyles} from '@styles/styles';
-import {type ThemeColors} from '@styles/themes/types';
-import positioning from '@styles/utilities/positioning';
-import spacing from '@styles/utilities/spacing';
+import fontFamily from '@styles/utils/fontFamily';
+import positioning from '@styles/utils/positioning';
+import roundToNearestMultipleOfFour from '@styles/utils/roundToNearestMultipleOfFour';
+import spacing from '@styles/utils/spacing';
import variables from '@styles/variables';
-import roundToNearestMultipleOfFour from './roundToNearestMultipleOfFour';
+import StyleUtilGenerator from './types';
/** This defines the proximity with the edge of the window in which tooltips should not be displayed.
* If a tooltip is too close to the edge of the screen, we'll shift it towards the center. */
@@ -116,6 +115,8 @@ type TooltipParams = {
manualShiftVertical?: number;
};
+type GetTooltipStylesStyleUtil = {getTooltipStyles: (props: TooltipParams) => TooltipStyles};
+
/**
* Generate styles for the tooltip component.
*
@@ -137,7 +138,7 @@ type TooltipParams = {
* @param [manualShiftVertical] - Any additional amount to manually shift the tooltip up or down.
* A positive value shifts it down, and a negative value shifts it up.
*/
-const createTooltipStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
+const createTooltipStyleUtils: StyleUtilGenerator = ({theme, styles}) => ({
getTooltipStyles: ({
tooltip,
currentSize,
@@ -151,7 +152,7 @@ const createTooltipStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
tooltipWrapperHeight,
manualShiftHorizontal = 0,
manualShiftVertical = 0,
- }: TooltipParams): TooltipStyles => {
+ }) => {
const tooltipVerticalPadding = spacing.pv1;
// We calculate tooltip width based on the tooltip's content width
diff --git a/src/styles/utils/generators/types.ts b/src/styles/utils/generators/types.ts
new file mode 100644
index 000000000000..ca6a630d94c5
--- /dev/null
+++ b/src/styles/utils/generators/types.ts
@@ -0,0 +1,6 @@
+import {ThemeStyles} from '@styles/index';
+import {ThemeColors} from '@styles/theme/types';
+
+type StyleUtilGenerator> = (props: {theme: ThemeColors; styles: ThemeStyles}) => StyleUtil;
+
+export default StyleUtilGenerator;
diff --git a/src/styles/getContextMenuItemStyles/index.native.ts b/src/styles/utils/getContextMenuItemStyles/index.native.ts
similarity index 100%
rename from src/styles/getContextMenuItemStyles/index.native.ts
rename to src/styles/utils/getContextMenuItemStyles/index.native.ts
diff --git a/src/styles/getContextMenuItemStyles/index.ts b/src/styles/utils/getContextMenuItemStyles/index.ts
similarity index 100%
rename from src/styles/getContextMenuItemStyles/index.ts
rename to src/styles/utils/getContextMenuItemStyles/index.ts
diff --git a/src/styles/getContextMenuItemStyles/types.ts b/src/styles/utils/getContextMenuItemStyles/types.ts
similarity index 77%
rename from src/styles/getContextMenuItemStyles/types.ts
rename to src/styles/utils/getContextMenuItemStyles/types.ts
index 376fb8d46d7c..06b989becf8a 100644
--- a/src/styles/getContextMenuItemStyles/types.ts
+++ b/src/styles/utils/getContextMenuItemStyles/types.ts
@@ -1,5 +1,5 @@
import {ViewStyle} from 'react-native';
-import {type ThemeStyles} from '@styles/styles';
+import {type ThemeStyles} from '@styles/index';
type GetContextMenuItemStyle = (styles: ThemeStyles, windowWidth?: number) => ViewStyle[];
diff --git a/src/styles/getNavigationModalCardStyles/index.desktop.ts b/src/styles/utils/getNavigationModalCardStyles/index.desktop.ts
similarity index 90%
rename from src/styles/getNavigationModalCardStyles/index.desktop.ts
rename to src/styles/utils/getNavigationModalCardStyles/index.desktop.ts
index 9e182636ad76..523f82048a02 100644
--- a/src/styles/getNavigationModalCardStyles/index.desktop.ts
+++ b/src/styles/utils/getNavigationModalCardStyles/index.desktop.ts
@@ -1,4 +1,4 @@
-import positioning from '@styles/utilities/positioning';
+import positioning from '@styles/utils/positioning';
import GetNavigationModalCardStyles from './types';
const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
diff --git a/src/styles/getNavigationModalCardStyles/index.ts b/src/styles/utils/getNavigationModalCardStyles/index.ts
similarity index 100%
rename from src/styles/getNavigationModalCardStyles/index.ts
rename to src/styles/utils/getNavigationModalCardStyles/index.ts
diff --git a/src/styles/getNavigationModalCardStyles/index.website.ts b/src/styles/utils/getNavigationModalCardStyles/index.website.ts
similarity index 90%
rename from src/styles/getNavigationModalCardStyles/index.website.ts
rename to src/styles/utils/getNavigationModalCardStyles/index.website.ts
index 9e182636ad76..523f82048a02 100644
--- a/src/styles/getNavigationModalCardStyles/index.website.ts
+++ b/src/styles/utils/getNavigationModalCardStyles/index.website.ts
@@ -1,4 +1,4 @@
-import positioning from '@styles/utilities/positioning';
+import positioning from '@styles/utils/positioning';
import GetNavigationModalCardStyles from './types';
const getNavigationModalCardStyles: GetNavigationModalCardStyles = () => ({
diff --git a/src/styles/getNavigationModalCardStyles/types.ts b/src/styles/utils/getNavigationModalCardStyles/types.ts
similarity index 100%
rename from src/styles/getNavigationModalCardStyles/types.ts
rename to src/styles/utils/getNavigationModalCardStyles/types.ts
diff --git a/src/styles/getPopOverVerticalOffset/index.desktop.ts b/src/styles/utils/getPopOverVerticalOffset/index.desktop.ts
similarity index 100%
rename from src/styles/getPopOverVerticalOffset/index.desktop.ts
rename to src/styles/utils/getPopOverVerticalOffset/index.desktop.ts
diff --git a/src/styles/getPopOverVerticalOffset/index.ts b/src/styles/utils/getPopOverVerticalOffset/index.ts
similarity index 100%
rename from src/styles/getPopOverVerticalOffset/index.ts
rename to src/styles/utils/getPopOverVerticalOffset/index.ts
diff --git a/src/styles/getPopOverVerticalOffset/types.ts b/src/styles/utils/getPopOverVerticalOffset/types.ts
similarity index 100%
rename from src/styles/getPopOverVerticalOffset/types.ts
rename to src/styles/utils/getPopOverVerticalOffset/types.ts
diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts
index 8d52c8de200a..c392e61f0814 100644
--- a/src/styles/utils/index.ts
+++ b/src/styles/utils/index.ts
@@ -1,65 +1,38 @@
import {CSSProperties} from 'react';
-import {Animated, DimensionValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
+import {Animated, DimensionValue, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
import {EdgeInsets} from 'react-native-safe-area-context';
import {ValueOf} from 'type-fest';
import * as Browser from '@libs/Browser';
import * as UserUtils from '@libs/UserUtils';
-import colors from '@styles/colors';
-import containerComposeStyles from '@styles/containerComposeStyles';
-import fontFamily from '@styles/fontFamily';
-import getContextMenuItemStyles from '@styles/getContextMenuItemStyles';
-import {compactContentContainerStyles} from '@styles/optionRowStyles';
-import {defaultStyles, type ThemeStyles} from '@styles/styles';
-import {defaultTheme} from '@styles/themes/themes';
-import {ThemeColors} from '@styles/themes/types';
-import cursor from '@styles/utilities/cursor';
-import positioning from '@styles/utilities/positioning';
-import spacing from '@styles/utilities/spacing';
+import {defaultTheme} from '@styles/theme';
+import colors from '@styles/theme/colors';
+import {ThemeColors} from '@styles/theme/types';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import {Transaction} from '@src/types/onyx';
-import createModalStyleUtils from './ModalStyleUtils';
-import createReportActionContextMenuStyleUtils from './ReportActionContextMenuStyleUtils';
-import createTooltipStyleUtils from './TooltipStyleUtils';
-
-type AllStyles = ViewStyle | TextStyle | ImageStyle;
-type ParsableStyle = StyleProp | ((state: PressableStateCallbackType) => StyleProp);
-
-type ColorValue = ValueOf;
-type AvatarSizeName = ValueOf;
-type EReceiptColorName = ValueOf;
-type AvatarSizeValue = ValueOf<
- Pick<
- typeof variables,
- | 'avatarSizeNormal'
- | 'avatarSizeSmallSubscript'
- | 'avatarSizeMidSubscript'
- | 'avatarSizeSubscript'
- | 'avatarSizeSmall'
- | 'avatarSizeSmaller'
- | 'avatarSizeXLarge'
- | 'avatarSizeLarge'
- | 'avatarSizeMedium'
- | 'avatarSizeLargeBordered'
- | 'avatarSizeHeader'
- | 'avatarSizeMentionIcon'
- | 'avatarSizeSmallNormal'
- >
->;
-
-type AvatarStyle = {
- width: number;
- height: number;
- borderRadius: number;
- backgroundColor: string;
-};
-
-type ButtonSizeValue = ValueOf;
-type ButtonStateName = ValueOf;
-type AvatarSize = {width: number};
-
-type WorkspaceColorStyle = {backgroundColor: ColorValue; fill: ColorValue};
-type EreceiptColorStyle = {backgroundColor: ColorValue; color: ColorValue};
+import {defaultStyles, type ThemeStyles} from '..';
+import containerComposeStyles from './containerComposeStyles';
+import fontFamily from './fontFamily';
+import createModalStyleUtils from './generators/ModalStyleUtils';
+import createReportActionContextMenuStyleUtils from './generators/ReportActionContextMenuStyleUtils';
+import createTooltipStyleUtils from './generators/TooltipStyleUtils';
+import getContextMenuItemStyles from './getContextMenuItemStyles';
+import {compactContentContainerStyles} from './optionRowStyles';
+import positioning from './positioning';
+import spacing from './spacing';
+import {
+ AllStyles,
+ AvatarSize,
+ AvatarSizeName,
+ AvatarSizeValue,
+ AvatarStyle,
+ ButtonSizeValue,
+ ButtonStateName,
+ EReceiptColorName,
+ EreceiptColorStyle,
+ ParsableStyle,
+ WorkspaceColorStyle,
+} from './types';
const workspaceColorOptions: WorkspaceColorStyle[] = [
{backgroundColor: colors.blue200, fill: colors.blue700},
@@ -1103,9 +1076,13 @@ const staticStyleUtils = {
const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
...staticStyleUtils,
- ...createModalStyleUtils(theme, styles),
- ...createTooltipStyleUtils(theme, styles),
- ...createReportActionContextMenuStyleUtils(theme, styles),
+ ...createModalStyleUtils({theme, styles}),
+ ...createTooltipStyleUtils({theme, styles}),
+ ...createReportActionContextMenuStyleUtils({theme, styles}),
+
+ getCompactContentContainerStyles: () => compactContentContainerStyles(styles),
+ getContextMenuItemStyles: (windowWidth?: number) => getContextMenuItemStyles(styles, windowWidth),
+ getContainerComposeStyles: () => containerComposeStyles(styles),
/**
* Gets styles for AutoCompleteSuggestion row
@@ -1236,7 +1213,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
getDisabledLinkStyles: (isDisabled = false): ViewStyle => {
const disabledLinkStyles = {
color: theme.textSupporting,
- ...cursor.cursorDisabled,
+ ...styles.cursorDisabled,
};
// TODO: Remove this "eslint-disable-next" once the theme switching migration is done and styles are fully typed (GH Issue: https://github.com/Expensify/App/issues/27337)
@@ -1247,6 +1224,19 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
};
},
+ /**
+ * Get the style for the AM and PM buttons in the TimePicker
+ */
+ getStatusAMandPMButtonStyle: (amPmValue: string): {styleForAM: ViewStyle; styleForPM: ViewStyle} => {
+ const computedStyleForAM: ViewStyle = amPmValue !== CONST.TIME_PERIOD.AM ? {backgroundColor: theme.componentBG} : {};
+ const computedStyleForPM: ViewStyle = amPmValue !== CONST.TIME_PERIOD.PM ? {backgroundColor: theme.componentBG} : {};
+
+ return {
+ styleForAM: [styles.timePickerWidth100, computedStyleForAM] as unknown as ViewStyle,
+ styleForPM: [styles.timePickerWidth100, computedStyleForPM] as unknown as ViewStyle,
+ };
+ },
+
/**
* Get the styles of the text next to dot indicators
*/
@@ -1440,12 +1430,6 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
return containerStyles;
},
-
- getCompactContentContainerStyles: () => compactContentContainerStyles(styles),
-
- getContextMenuItemStyles: (windowWidth?: number) => getContextMenuItemStyles(styles, windowWidth),
-
- getContainerComposeStyles: () => containerComposeStyles(styles),
});
type StyleUtilsType = ReturnType;
diff --git a/src/styles/italic/index.android.ts b/src/styles/utils/italic/index.android.ts
similarity index 100%
rename from src/styles/italic/index.android.ts
rename to src/styles/utils/italic/index.android.ts
diff --git a/src/styles/italic/index.ts b/src/styles/utils/italic/index.ts
similarity index 100%
rename from src/styles/italic/index.ts
rename to src/styles/utils/italic/index.ts
diff --git a/src/styles/italic/types.ts b/src/styles/utils/italic/types.ts
similarity index 100%
rename from src/styles/italic/types.ts
rename to src/styles/utils/italic/types.ts
diff --git a/src/styles/utilities/objectFit.ts b/src/styles/utils/objectFit.ts
similarity index 100%
rename from src/styles/utilities/objectFit.ts
rename to src/styles/utils/objectFit.ts
diff --git a/src/styles/optionAlternateTextPlatformStyles/index.ios.ts b/src/styles/utils/optionAlternateTextPlatformStyles/index.ios.ts
similarity index 100%
rename from src/styles/optionAlternateTextPlatformStyles/index.ios.ts
rename to src/styles/utils/optionAlternateTextPlatformStyles/index.ios.ts
diff --git a/src/styles/optionAlternateTextPlatformStyles/index.ts b/src/styles/utils/optionAlternateTextPlatformStyles/index.ts
similarity index 100%
rename from src/styles/optionAlternateTextPlatformStyles/index.ts
rename to src/styles/utils/optionAlternateTextPlatformStyles/index.ts
diff --git a/src/styles/optionAlternateTextPlatformStyles/types.ts b/src/styles/utils/optionAlternateTextPlatformStyles/types.ts
similarity index 100%
rename from src/styles/optionAlternateTextPlatformStyles/types.ts
rename to src/styles/utils/optionAlternateTextPlatformStyles/types.ts
diff --git a/src/styles/optionRowStyles/index.native.ts b/src/styles/utils/optionRowStyles/index.native.ts
similarity index 100%
rename from src/styles/optionRowStyles/index.native.ts
rename to src/styles/utils/optionRowStyles/index.native.ts
diff --git a/src/styles/optionRowStyles/index.ts b/src/styles/utils/optionRowStyles/index.ts
similarity index 100%
rename from src/styles/optionRowStyles/index.ts
rename to src/styles/utils/optionRowStyles/index.ts
diff --git a/src/styles/optionRowStyles/types.ts b/src/styles/utils/optionRowStyles/types.ts
similarity index 76%
rename from src/styles/optionRowStyles/types.ts
rename to src/styles/utils/optionRowStyles/types.ts
index 3425d7812be2..a31b94e0fc79 100644
--- a/src/styles/optionRowStyles/types.ts
+++ b/src/styles/utils/optionRowStyles/types.ts
@@ -1,5 +1,5 @@
import {ViewStyle} from 'react-native';
-import {type ThemeStyles} from '@styles/styles';
+import {type ThemeStyles} from '@styles/index';
type CompactContentContainerStyles = (styles: ThemeStyles) => ViewStyle;
diff --git a/src/styles/utilities/overflow.ts b/src/styles/utils/overflow.ts
similarity index 100%
rename from src/styles/utilities/overflow.ts
rename to src/styles/utils/overflow.ts
diff --git a/src/styles/utilities/overflowAuto/index.native.ts b/src/styles/utils/overflowAuto/index.native.ts
similarity index 100%
rename from src/styles/utilities/overflowAuto/index.native.ts
rename to src/styles/utils/overflowAuto/index.native.ts
diff --git a/src/styles/utilities/overflowAuto/index.ts b/src/styles/utils/overflowAuto/index.ts
similarity index 100%
rename from src/styles/utilities/overflowAuto/index.ts
rename to src/styles/utils/overflowAuto/index.ts
diff --git a/src/styles/utilities/overflowAuto/types.ts b/src/styles/utils/overflowAuto/types.ts
similarity index 100%
rename from src/styles/utilities/overflowAuto/types.ts
rename to src/styles/utils/overflowAuto/types.ts
diff --git a/src/styles/overflowXHidden/index.native.ts b/src/styles/utils/overflowXHidden/index.native.ts
similarity index 100%
rename from src/styles/overflowXHidden/index.native.ts
rename to src/styles/utils/overflowXHidden/index.native.ts
diff --git a/src/styles/overflowXHidden/index.ts b/src/styles/utils/overflowXHidden/index.ts
similarity index 100%
rename from src/styles/overflowXHidden/index.ts
rename to src/styles/utils/overflowXHidden/index.ts
diff --git a/src/styles/overflowXHidden/types.ts b/src/styles/utils/overflowXHidden/types.ts
similarity index 100%
rename from src/styles/overflowXHidden/types.ts
rename to src/styles/utils/overflowXHidden/types.ts
diff --git a/src/styles/utilities/overscrollBehaviorContain/index.native.ts b/src/styles/utils/overscrollBehaviorContain/index.native.ts
similarity index 100%
rename from src/styles/utilities/overscrollBehaviorContain/index.native.ts
rename to src/styles/utils/overscrollBehaviorContain/index.native.ts
diff --git a/src/styles/utilities/overscrollBehaviorContain/index.ts b/src/styles/utils/overscrollBehaviorContain/index.ts
similarity index 100%
rename from src/styles/utilities/overscrollBehaviorContain/index.ts
rename to src/styles/utils/overscrollBehaviorContain/index.ts
diff --git a/src/styles/utilities/overscrollBehaviorContain/types.ts b/src/styles/utils/overscrollBehaviorContain/types.ts
similarity index 100%
rename from src/styles/utilities/overscrollBehaviorContain/types.ts
rename to src/styles/utils/overscrollBehaviorContain/types.ts
diff --git a/src/styles/pointerEventsAuto/index.native.ts b/src/styles/utils/pointerEventsAuto/index.native.ts
similarity index 100%
rename from src/styles/pointerEventsAuto/index.native.ts
rename to src/styles/utils/pointerEventsAuto/index.native.ts
diff --git a/src/styles/pointerEventsAuto/index.ts b/src/styles/utils/pointerEventsAuto/index.ts
similarity index 100%
rename from src/styles/pointerEventsAuto/index.ts
rename to src/styles/utils/pointerEventsAuto/index.ts
diff --git a/src/styles/pointerEventsAuto/types.ts b/src/styles/utils/pointerEventsAuto/types.ts
similarity index 100%
rename from src/styles/pointerEventsAuto/types.ts
rename to src/styles/utils/pointerEventsAuto/types.ts
diff --git a/src/styles/pointerEventsBoxNone/index.native.ts b/src/styles/utils/pointerEventsBoxNone/index.native.ts
similarity index 100%
rename from src/styles/pointerEventsBoxNone/index.native.ts
rename to src/styles/utils/pointerEventsBoxNone/index.native.ts
diff --git a/src/styles/pointerEventsBoxNone/index.ts b/src/styles/utils/pointerEventsBoxNone/index.ts
similarity index 100%
rename from src/styles/pointerEventsBoxNone/index.ts
rename to src/styles/utils/pointerEventsBoxNone/index.ts
diff --git a/src/styles/pointerEventsBoxNone/types.ts b/src/styles/utils/pointerEventsBoxNone/types.ts
similarity index 100%
rename from src/styles/pointerEventsBoxNone/types.ts
rename to src/styles/utils/pointerEventsBoxNone/types.ts
diff --git a/src/styles/pointerEventsNone/index.native.ts b/src/styles/utils/pointerEventsNone/index.native.ts
similarity index 100%
rename from src/styles/pointerEventsNone/index.native.ts
rename to src/styles/utils/pointerEventsNone/index.native.ts
diff --git a/src/styles/pointerEventsNone/index.ts b/src/styles/utils/pointerEventsNone/index.ts
similarity index 100%
rename from src/styles/pointerEventsNone/index.ts
rename to src/styles/utils/pointerEventsNone/index.ts
diff --git a/src/styles/pointerEventsNone/types.ts b/src/styles/utils/pointerEventsNone/types.ts
similarity index 100%
rename from src/styles/pointerEventsNone/types.ts
rename to src/styles/utils/pointerEventsNone/types.ts
diff --git a/src/styles/utilities/positioning.ts b/src/styles/utils/positioning.ts
similarity index 100%
rename from src/styles/utilities/positioning.ts
rename to src/styles/utils/positioning.ts
diff --git a/src/styles/utilities/sizing.ts b/src/styles/utils/sizing.ts
similarity index 100%
rename from src/styles/utilities/sizing.ts
rename to src/styles/utils/sizing.ts
diff --git a/src/styles/utilities/spacing.ts b/src/styles/utils/spacing.ts
similarity index 99%
rename from src/styles/utilities/spacing.ts
rename to src/styles/utils/spacing.ts
index 7d568847ab65..b2597fc64603 100644
--- a/src/styles/utilities/spacing.ts
+++ b/src/styles/utils/spacing.ts
@@ -271,6 +271,10 @@ export default {
marginBottom: 40,
},
+ mb12: {
+ marginBottom: 48,
+ },
+
mb15: {
marginBottom: 60,
},
diff --git a/src/styles/utilities/textDecorationLine.ts b/src/styles/utils/textDecorationLine.ts
similarity index 100%
rename from src/styles/utilities/textDecorationLine.ts
rename to src/styles/utils/textDecorationLine.ts
diff --git a/src/styles/utilities/textUnderline/index.native.ts b/src/styles/utils/textUnderline/index.native.ts
similarity index 100%
rename from src/styles/utilities/textUnderline/index.native.ts
rename to src/styles/utils/textUnderline/index.native.ts
diff --git a/src/styles/utilities/textUnderline/index.ts b/src/styles/utils/textUnderline/index.ts
similarity index 100%
rename from src/styles/utilities/textUnderline/index.ts
rename to src/styles/utils/textUnderline/index.ts
diff --git a/src/styles/utilities/textUnderline/types.ts b/src/styles/utils/textUnderline/types.ts
similarity index 100%
rename from src/styles/utilities/textUnderline/types.ts
rename to src/styles/utils/textUnderline/types.ts
diff --git a/src/styles/utils/types.ts b/src/styles/utils/types.ts
new file mode 100644
index 000000000000..c7e1fc60a142
--- /dev/null
+++ b/src/styles/utils/types.ts
@@ -0,0 +1,59 @@
+import {ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
+import {ValueOf} from 'type-fest';
+import type colors from '@styles/theme/colors';
+import type variables from '@styles/variables';
+import type CONST from '@src/CONST';
+
+type AllStyles = ViewStyle | TextStyle | ImageStyle;
+type ParsableStyle = StyleProp | ((state: PressableStateCallbackType) => StyleProp);
+
+type ColorValue = ValueOf;
+type AvatarSizeName = ValueOf;
+type EReceiptColorName = ValueOf;
+type AvatarSizeValue = ValueOf<
+ Pick<
+ typeof variables,
+ | 'avatarSizeNormal'
+ | 'avatarSizeSmallSubscript'
+ | 'avatarSizeMidSubscript'
+ | 'avatarSizeSubscript'
+ | 'avatarSizeSmall'
+ | 'avatarSizeSmaller'
+ | 'avatarSizeXLarge'
+ | 'avatarSizeLarge'
+ | 'avatarSizeMedium'
+ | 'avatarSizeLargeBordered'
+ | 'avatarSizeHeader'
+ | 'avatarSizeMentionIcon'
+ | 'avatarSizeSmallNormal'
+ >
+>;
+
+type AvatarStyle = {
+ width: number;
+ height: number;
+ borderRadius: number;
+ backgroundColor: string;
+};
+
+type ButtonSizeValue = ValueOf;
+type ButtonStateName = ValueOf;
+type AvatarSize = {width: number};
+
+type WorkspaceColorStyle = {backgroundColor: ColorValue; fill: ColorValue};
+type EreceiptColorStyle = {backgroundColor: ColorValue; color: ColorValue};
+
+export type {
+ AllStyles,
+ ParsableStyle,
+ ColorValue,
+ AvatarSizeName,
+ EReceiptColorName,
+ AvatarSizeValue,
+ AvatarStyle,
+ ButtonSizeValue,
+ ButtonStateName,
+ AvatarSize,
+ WorkspaceColorStyle,
+ EreceiptColorStyle,
+};
diff --git a/src/styles/utilities/userSelect/index.native.ts b/src/styles/utils/userSelect/index.native.ts
similarity index 100%
rename from src/styles/utilities/userSelect/index.native.ts
rename to src/styles/utils/userSelect/index.native.ts
diff --git a/src/styles/utilities/userSelect/index.ts b/src/styles/utils/userSelect/index.ts
similarity index 100%
rename from src/styles/utilities/userSelect/index.ts
rename to src/styles/utils/userSelect/index.ts
diff --git a/src/styles/utilities/userSelect/types.ts b/src/styles/utils/userSelect/types.ts
similarity index 100%
rename from src/styles/utilities/userSelect/types.ts
rename to src/styles/utils/userSelect/types.ts
diff --git a/src/styles/utilities/visibility/index.native.ts b/src/styles/utils/visibility/index.native.ts
similarity index 100%
rename from src/styles/utilities/visibility/index.native.ts
rename to src/styles/utils/visibility/index.native.ts
diff --git a/src/styles/utilities/visibility/index.ts b/src/styles/utils/visibility/index.ts
similarity index 100%
rename from src/styles/utilities/visibility/index.ts
rename to src/styles/utils/visibility/index.ts
diff --git a/src/styles/utilities/visibility/types.ts b/src/styles/utils/visibility/types.ts
similarity index 100%
rename from src/styles/utilities/visibility/types.ts
rename to src/styles/utils/visibility/types.ts
diff --git a/src/styles/utilities/whiteSpace/index.native.ts b/src/styles/utils/whiteSpace/index.native.ts
similarity index 100%
rename from src/styles/utilities/whiteSpace/index.native.ts
rename to src/styles/utils/whiteSpace/index.native.ts
diff --git a/src/styles/utilities/whiteSpace/index.ts b/src/styles/utils/whiteSpace/index.ts
similarity index 100%
rename from src/styles/utilities/whiteSpace/index.ts
rename to src/styles/utils/whiteSpace/index.ts
diff --git a/src/styles/utilities/whiteSpace/types.ts b/src/styles/utils/whiteSpace/types.ts
similarity index 100%
rename from src/styles/utilities/whiteSpace/types.ts
rename to src/styles/utils/whiteSpace/types.ts
diff --git a/src/styles/utilities/wordBreak/index.native.ts b/src/styles/utils/wordBreak/index.native.ts
similarity index 100%
rename from src/styles/utilities/wordBreak/index.native.ts
rename to src/styles/utils/wordBreak/index.native.ts
diff --git a/src/styles/utilities/wordBreak/index.ts b/src/styles/utils/wordBreak/index.ts
similarity index 100%
rename from src/styles/utilities/wordBreak/index.ts
rename to src/styles/utils/wordBreak/index.ts
diff --git a/src/styles/utilities/wordBreak/types.ts b/src/styles/utils/wordBreak/types.ts
similarity index 100%
rename from src/styles/utilities/wordBreak/types.ts
rename to src/styles/utils/wordBreak/types.ts
diff --git a/src/styles/utilities/writingDirection.ts b/src/styles/utils/writingDirection.ts
similarity index 100%
rename from src/styles/utilities/writingDirection.ts
rename to src/styles/utils/writingDirection.ts
diff --git a/src/types/modules/material-top-tabs.d.ts b/src/types/modules/material-top-tabs.d.ts
new file mode 100644
index 000000000000..693d82d07c57
--- /dev/null
+++ b/src/types/modules/material-top-tabs.d.ts
@@ -0,0 +1,8 @@
+/** This direct import is required, because this function was added by a patch,
+ * and its typings are not supported by default */
+import {useTabAnimation} from '@react-navigation/material-top-tabs/src/utils/useTabAnimation';
+
+declare module '@react-navigation/material-top-tabs' {
+ // eslint-disable-next-line import/prefer-default-export
+ export {useTabAnimation};
+}
diff --git a/src/types/onyx/BankAccount.ts b/src/types/onyx/BankAccount.ts
index 4dd46c82f800..8e26faf518cb 100644
--- a/src/types/onyx/BankAccount.ts
+++ b/src/types/onyx/BankAccount.ts
@@ -45,5 +45,7 @@ type BankAccount = {
pendingAction?: OnyxCommon.PendingAction;
};
+type BankAccountList = Record;
+
export default BankAccount;
-export type {AccountData, AdditionalData};
+export type {AccountData, AdditionalData, BankAccountList};
diff --git a/src/types/onyx/Fund.ts b/src/types/onyx/Fund.ts
index 82c15c5089d7..e889a414062e 100644
--- a/src/types/onyx/Fund.ts
+++ b/src/types/onyx/Fund.ts
@@ -37,4 +37,7 @@ type Fund = {
pendingAction?: OnyxCommon.PendingAction;
};
+type FundList = Record;
+
export default Fund;
+export type {FundList};
diff --git a/src/types/onyx/Login.ts b/src/types/onyx/Login.ts
index c770e2f81f90..bcf949eb95e6 100644
--- a/src/types/onyx/Login.ts
+++ b/src/types/onyx/Login.ts
@@ -17,4 +17,7 @@ type Login = {
pendingFields?: OnyxCommon.PendingFields;
};
+type LoginList = Record;
+
export default Login;
+export type {LoginList};
diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts
index 7d18f4d70c8d..110bdb024a8c 100644
--- a/src/types/onyx/index.ts
+++ b/src/types/onyx/index.ts
@@ -1,6 +1,6 @@
import Account from './Account';
import AccountData from './AccountData';
-import BankAccount from './BankAccount';
+import BankAccount, {BankAccountList} from './BankAccount';
import Beta from './Beta';
import BlockedFromConcierge from './BlockedFromConcierge';
import Card from './Card';
@@ -11,10 +11,10 @@ import DemoInfo from './DemoInfo';
import Download from './Download';
import Form, {AddDebitCardForm, DateOfBirthForm} from './Form';
import FrequentlyUsedEmoji from './FrequentlyUsedEmoji';
-import Fund from './Fund';
+import Fund, {FundList} from './Fund';
import IOU from './IOU';
import Locale from './Locale';
-import Login from './Login';
+import Login, {LoginList} from './Login';
import MapboxAccessToken from './MapboxAccessToken';
import Modal from './Modal';
import Network from './Network';
@@ -61,6 +61,7 @@ export type {
AccountData,
AddDebitCardForm,
BankAccount,
+ BankAccountList,
Beta,
BlockedFromConcierge,
Card,
@@ -73,9 +74,11 @@ export type {
Form,
FrequentlyUsedEmoji,
Fund,
+ FundList,
IOU,
Locale,
Login,
+ LoginList,
MapboxAccessToken,
Modal,
Network,
diff --git a/tests/ui/UnreadIndicatorsTest.js b/tests/ui/UnreadIndicatorsTest.js
index ed44d3088ae0..93bb2cb94d30 100644
--- a/tests/ui/UnreadIndicatorsTest.js
+++ b/tests/ui/UnreadIndicatorsTest.js
@@ -20,7 +20,7 @@ import * as Pusher from '../../src/libs/Pusher/pusher';
import PusherConnectionManager from '../../src/libs/PusherConnectionManager';
import ONYXKEYS from '../../src/ONYXKEYS';
import appSetup from '../../src/setup';
-import fontWeightBold from '../../src/styles/fontWeight/bold';
+import fontWeightBold from '../../src/styles/utils/fontWeight/bold';
import * as TestHelper from '../utils/TestHelper';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct';
diff --git a/tests/unit/ReportActionsUtilsTest.js b/tests/unit/ReportActionsUtilsTest.js
index b8b6eb5e7673..545d442e4799 100644
--- a/tests/unit/ReportActionsUtilsTest.js
+++ b/tests/unit/ReportActionsUtilsTest.js
@@ -288,7 +288,7 @@ describe('ReportActionsUtils', () => {
expect(result).toStrictEqual(input);
});
- it('should filter out deleted, non-pending comments', () => {
+ it('should filter out deleted and delete-pending comments', () => {
const input = [
{
created: '2022-11-13 22:27:01.825',
@@ -312,6 +312,7 @@ describe('ReportActionsUtils', () => {
];
const result = ReportActionsUtils.getSortedReportActionsForDisplay(input);
input.pop();
+ input.pop();
expect(result).toStrictEqual(input);
});
});
diff --git a/workflow_tests/assertions/createNewVersionAssertions.js b/workflow_tests/assertions/createNewVersionAssertions.js
index 27c54e924975..e4526ae59be2 100644
--- a/workflow_tests/assertions/createNewVersionAssertions.js
+++ b/workflow_tests/assertions/createNewVersionAssertions.js
@@ -26,19 +26,7 @@ const assertCreateNewVersionJobExecuted = (workflowResult, semverLevel = 'BUILD'
],
[],
),
- utils.createStepAssertion(
- 'Setup git for OSBotify',
- true,
- null,
- 'CREATENEWVERSION',
- 'Setup git for OSBotify',
- [
- {key: 'GPG_PASSPHRASE', value: '***'},
- {key: 'OS_BOTIFY_APP_ID', value: '***'},
- {key: 'OS_BOTIFY_PRIVATE_KEY', value: '***'},
- ],
- [],
- ),
+ utils.createStepAssertion('Setup git for OSBotify', true, null, 'CREATENEWVERSION', 'Setup git for OSBotify', [{key: 'GPG_PASSPHRASE', value: '***'}], []),
utils.createStepAssertion(
'Generate version',
true,
@@ -46,7 +34,7 @@ const assertCreateNewVersionJobExecuted = (workflowResult, semverLevel = 'BUILD'
'CREATENEWVERSION',
'Generate version',
[
- {key: 'GITHUB_TOKEN', value: 'os_botify_api_token'},
+ {key: 'GITHUB_TOKEN', value: '***'},
{key: 'SEMVER_LEVEL', value: semverLevel},
],
[],
diff --git a/workflow_tests/mocks/createNewVersionMocks.js b/workflow_tests/mocks/createNewVersionMocks.js
index 5e82e2102ef0..a1f601aef47f 100644
--- a/workflow_tests/mocks/createNewVersionMocks.js
+++ b/workflow_tests/mocks/createNewVersionMocks.js
@@ -21,9 +21,8 @@ const CREATENEWVERSION__CREATENEWVERSION__SETUP_GIT_FOR_OSBOTIFY__STEP_MOCK = ut
'Setup git for OSBotify',
'Setup git for OSBotify',
'CREATENEWVERSION',
- ['GPG_PASSPHRASE', 'OS_BOTIFY_APP_ID', 'OS_BOTIFY_PRIVATE_KEY'],
+ ['GPG_PASSPHRASE'],
[],
- {OS_BOTIFY_API_TOKEN: 'os_botify_api_token'},
);
const CREATENEWVERSION__CREATENEWVERSION__GENERATE_VERSION__STEP_MOCK = utils.createMockStep(
'Generate version',