diff --git a/.eslintrc.js b/.eslintrc.js index e0ebd2252c3d..5c23c7be0839 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -175,6 +175,7 @@ module.exports = { 'es/no-optional-chaining': 'off', 'valid-jsdoc': 'off', 'jsdoc/no-types': 'error', + 'rulesdir/no-default-props': 'error', 'import/no-extraneous-dependencies': 'off', 'rulesdir/prefer-underscore-method': 'off', 'rulesdir/prefer-import-module-contents': 'off', diff --git a/.github/scripts/verifyPodfile.sh b/.github/scripts/verifyPodfile.sh index ec2709a25786..cd94a49bb091 100755 --- a/.github/scripts/verifyPodfile.sh +++ b/.github/scripts/verifyPodfile.sh @@ -12,7 +12,7 @@ declare EXIT_CODE=0 # Check Provisioning Style. If automatic signing is enabled, iOS builds will fail, so ensure we always have the proper profile specified info "Verifying that automatic signing is not enabled" -if grep -q 'PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore' ios/NewExpensify.xcodeproj/project.pbxproj; then +if grep -q 'PROVISIONING_PROFILE_SPECIFIER = "(NewApp) AppStore"' ios/NewExpensify.xcodeproj/project.pbxproj; then success "Automatic signing not enabled" else error "Error: Automatic provisioning style is not allowed!" diff --git a/.github/workflows/README.md b/.github/workflows/README.md index d940d99d9cde..b2cc58fa4a6a 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -83,8 +83,10 @@ The GitHub workflows require a large list of secrets to deploy, notify and test 1. `LARGE_SECRET_PASSPHRASE` - decrypts secrets stored in various encrypted files stored in GitHub repository. To create updated versions of these encrypted files, refer to steps 1-4 of [this encrypted secrets help page](https://docs.github.com/en/actions/reference/encrypted-secrets#limits-for-secrets) using the `LARGE_SECRET_PASSPHRASE`. 1. `android/app/my-upload-key.keystore.gpg` 1. `android/app/android-fastlane-json-key.json.gpg` - 1. `ios/expensify_chat_adhoc.mobileprovision.gpg` - 1. `ios/chat_expensify_appstore.mobileprovision.gpg` + 1. `ios/NewApp_AdHoc.mobileprovision` + 1. `ios/NewApp_AdHoc_Notification_Service.mobileprovision` + 1. `ios/NewApp_AppStore.mobileprovision.gpg` + 1. `ios/NewApp_AppStore_Notification_Service.mobileprovision.gpg` 1. `ios/Certificates.p12.gpg` 1. `SLACK_WEBHOOK` - Sends Slack notifications via Slack WebHook https://expensify.slack.com/services/B01AX48D7MM 1. `OS_BOTIFY_TOKEN` - Personal access token for @OSBotify user in GitHub diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index 09113bdcc548..75c0b8497bdd 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -194,7 +194,7 @@ jobs: with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-west-1 + aws-region: us-west-2 - name: Schedule AWS Device Farm test run on main branch uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml index faf06cacc62f..6aeecb3b4e05 100644 --- a/.github/workflows/platformDeploy.yml +++ b/.github/workflows/platformDeploy.yml @@ -10,7 +10,7 @@ on: env: SHOULD_DEPLOY_PRODUCTION: ${{ github.event_name == 'release' }} - DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer concurrency: group: ${{ github.workflow }}-${{ github.event_name }} @@ -211,8 +211,13 @@ jobs: max_attempts: 5 command: cd ios && bundle exec pod install - - name: Decrypt profile - run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output chat_expensify_appstore.mobileprovision chat_expensify_appstore.mobileprovision.gpg + - name: Decrypt AppStore profile + run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AppStore.mobileprovision NewApp_AppStore.mobileprovision.gpg + env: + LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + + - name: Decrypt AppStore Notification Service profile + run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AppStore_Notification_Service.mobileprovision NewApp_AppStore_Notification_Service.mobileprovision.gpg env: LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 196d7115bfc4..8b18b8aa5d53 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -11,7 +11,7 @@ on: branches: ['*ci-test/**'] env: - DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer jobs: validateActor: @@ -159,7 +159,7 @@ jobs: uses: ./.github/actions/composite/setupNode - name: Setup XCode - run: sudo xcode-select -switch /Applications/Xcode_14.2.app + run: sudo xcode-select -switch /Applications/Xcode_15.0.1.app - name: Setup Ruby uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 @@ -187,8 +187,13 @@ jobs: max_attempts: 5 command: cd ios && bundle exec pod install - - name: Decrypt profile - run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output expensify_chat_adhoc.mobileprovision expensify_chat_adhoc.mobileprovision.gpg + - name: Decrypt AdHoc profile + run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AdHoc.mobileprovision NewApp_AdHoc.mobileprovision.gpg + env: + LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + + - name: Decrypt AdHoc Notification Service profile + run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AdHoc_Notification_Service.mobileprovision NewApp_AdHoc_Notification_Service.mobileprovision.gpg env: LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} diff --git a/.github/workflows/testGithubActionsWorkflows.yml b/.github/workflows/testGithubActionsWorkflows.yml index 58de3ba2d9f3..d052b343cf0c 100644 --- a/.github/workflows/testGithubActionsWorkflows.yml +++ b/.github/workflows/testGithubActionsWorkflows.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: workflow_call: pull_request: - types: [opened, reopened, edited, synchronize] + types: [opened, reopened, synchronize] branches-ignore: [staging, production] paths: ['.github/**'] diff --git a/README.md b/README.md index b2d51b2a1709..3b9010695760 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,9 @@ to help run our Unit tests. * To run the **Jest unit tests**: `npm run test` +## Performance tests +We use Reassure for monitoring performance regression. More detailed information can be found [here](tests/perf-test/README.md): + ---- # Debugging diff --git a/android/app/build.gradle b/android/app/build.gradle index 8e4daef2e6cb..e93150b48fca 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -96,8 +96,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001041707 - versionName "1.4.17-7" + versionCode 1001042101 + versionName "1.4.21-1" } flavorDimensions "default" diff --git a/assets/images/product-illustrations/telescope.svg b/assets/images/product-illustrations/telescope.svg new file mode 100644 index 000000000000..95617c801789 --- /dev/null +++ b/assets/images/product-illustrations/telescope.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__bigrocket.svg b/assets/images/simple-illustrations/simple-illustration__bigrocket.svg new file mode 100644 index 000000000000..1afd5f66b6ea --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__bigrocket.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__handcard.svg b/assets/images/simple-illustrations/simple-illustration__handcard.svg new file mode 100644 index 000000000000..7419b33d425c --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__handcard.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg b/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg index 732c16a75a2b..471b978bb97e 100644 --- a/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg +++ b/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg @@ -1 +1,98 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__mailbox.svg b/assets/images/simple-illustrations/simple-illustration__mailbox.svg new file mode 100644 index 000000000000..81b1f508fb52 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__mailbox.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__smallrocket.svg b/assets/images/simple-illustrations/simple-illustration__smallrocket.svg new file mode 100644 index 000000000000..0f8f166c849f --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__smallrocket.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_data/_routes.yml b/docs/_data/_routes.yml index 4246b23982ec..0887e90dcc8b 100644 --- a/docs/_data/_routes.yml +++ b/docs/_data/_routes.yml @@ -113,8 +113,8 @@ platforms: icon: /assets/images/hand-card.svg description: Explore how the Expensify Card combines convenience and security to enhance everyday business transactions. Discover how to apply for, oversee, and maximize your card perks here. - - href: get-paid-back - title: Get Paid Back + - href: payments + title: Payments icon: /assets/images/money-into-wallet.svg description: Whether you submit an expense report or an invoice, find out here how to ensure a smooth and timely payback process every time. diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md b/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md index 65361ba1af9a..0856e2694340 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md +++ b/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md @@ -3,7 +3,7 @@ title: Certinia description: Guide to connecting Expensify and Certinia FFA and PSA/SRP (formerly known as FinancialForce) --- # Overview -[Cetinia](https://use.expensify.com/financialforce) (Formerly known as FinancialForce)is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both. +[Cetinia](https://use.expensify.com/financialforce) (formerly known as FinancialForce) is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both. # Before connecting to Certinia Install the Expensify bundle in Certinia using the relevant installer: diff --git a/docs/articles/new-expensify/get-paid-back/Distance-Requests.md b/docs/articles/new-expensify/payments/Distance-Requests.md similarity index 100% rename from docs/articles/new-expensify/get-paid-back/Distance-Requests.md rename to docs/articles/new-expensify/payments/Distance-Requests.md diff --git a/docs/articles/new-expensify/get-paid-back/Referral-Program.md b/docs/articles/new-expensify/payments/Referral-Program.md similarity index 100% rename from docs/articles/new-expensify/get-paid-back/Referral-Program.md rename to docs/articles/new-expensify/payments/Referral-Program.md diff --git a/docs/articles/new-expensify/get-paid-back/Request-Money.md b/docs/articles/new-expensify/payments/Request-Money.md similarity index 100% rename from docs/articles/new-expensify/get-paid-back/Request-Money.md rename to docs/articles/new-expensify/payments/Request-Money.md diff --git a/docs/new-expensify/hubs/get-paid-back/index.html b/docs/new-expensify/hubs/payments/index.html similarity index 69% rename from docs/new-expensify/hubs/get-paid-back/index.html rename to docs/new-expensify/hubs/payments/index.html index 1f84c1510b92..d22f7e375f2e 100644 --- a/docs/new-expensify/hubs/get-paid-back/index.html +++ b/docs/new-expensify/hubs/payments/index.html @@ -1,6 +1,6 @@ --- layout: default -title: Get Paid Back +title: Payments --- {% include hub.html %} \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 2b5c15146eb3..b7d3334c902f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -161,19 +161,23 @@ platform :ios do ) install_provisioning_profile( - path: "./ios/expensify_chat_adhoc.mobileprovision" + path: "./ios/NewApp_AdHoc.mobileprovision" + ) + + install_provisioning_profile( + path: "./ios/NewApp_AdHoc_Notification_Service.mobileprovision" ) build_app( workspace: "./ios/NewExpensify.xcworkspace", skip_profile_detection: true, scheme: "New Expensify AdHoc", - xcargs: { :PROVISIONING_PROFILE_SPECIFIER => "expensify_chat_adhoc", }, export_method: "ad-hoc", export_options: { method: "ad-hoc", provisioningProfiles: { - "com.expensify.chat.adhoc" => "expensify_chat_adhoc", + "com.expensify.chat.adhoc" => "(NewApp) AdHoc", + "com.expensify.chat.adhoc.NotificationServiceExtension" => "(NewApp) AdHoc: Notification Service", }, manageAppVersionAndBuildNumber: false } @@ -215,7 +219,11 @@ platform :ios do ) install_provisioning_profile( - path: "./ios/chat_expensify_appstore.mobileprovision" + path: "./ios/NewApp_AppStore.mobileprovision" + ) + + install_provisioning_profile( + path: "./ios/NewApp_AppStore_Notification_Service.mobileprovision" ) build_app( @@ -223,6 +231,10 @@ platform :ios do scheme: "New Expensify", output_name: "New Expensify.ipa", export_options: { + provisioningProfiles: { + "com.chat.expensify.chat" => "(NewApp) AppStore", + "com.chat.expensify.chat.NotificationServiceExtension" => "(NewApp) AppStore: Notification Service", + }, manageAppVersionAndBuildNumber: false } ) diff --git a/ios/NewApp_AdHoc.mobileprovision.gpg b/ios/NewApp_AdHoc.mobileprovision.gpg new file mode 100644 index 000000000000..e5ee52210866 Binary files /dev/null and b/ios/NewApp_AdHoc.mobileprovision.gpg differ diff --git a/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg b/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg new file mode 100644 index 000000000000..ba9258840638 Binary files /dev/null and b/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg differ diff --git a/ios/NewApp_AppStore.mobileprovision.gpg b/ios/NewApp_AppStore.mobileprovision.gpg new file mode 100644 index 000000000000..2e73cc7661e3 Binary files /dev/null and b/ios/NewApp_AppStore.mobileprovision.gpg differ diff --git a/ios/NewApp_AppStore_Notification_Service.mobileprovision.gpg b/ios/NewApp_AppStore_Notification_Service.mobileprovision.gpg new file mode 100644 index 000000000000..4af7b16c5041 Binary files /dev/null and b/ios/NewApp_AppStore_Notification_Service.mobileprovision.gpg differ diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index 6b57929cfc2c..c239f4da183f 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 059DC4EFD39EF39437E6823D /* libPods-NotificationServiceExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A997AA8204EA3D90907FA80 /* libPods-NotificationServiceExtension.a */; }; 0C7C65547D7346EB923BE808 /* ExpensifyMono-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */; }; 0CDA8E34287DD650004ECBEC /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0CDA8E33287DD650004ECBEC /* AppDelegate.mm */; }; 0CDA8E35287DD650004ECBEC /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0CDA8E33287DD650004ECBEC /* AppDelegate.mm */; }; @@ -27,6 +28,9 @@ 7041848626A8E47D00E09F4D /* RCTStartupTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7041848426A8E47D00E09F4D /* RCTStartupTimer.m */; }; 70CF6E82262E297300711ADC /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 70CF6E81262E297300711ADC /* BootSplash.storyboard */; }; 7F5E81F06BCCF61AD02CEA06 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCD444BEDDB0AF1745B39049 /* ExpoModulesProvider.swift */; }; + 7F9DD8DA2B2A445B005E3AFA /* ExpError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F9DD8D92B2A445B005E3AFA /* ExpError.swift */; }; + 7FD73C9E2B23CE9500420AF3 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FD73C9D2B23CE9500420AF3 /* NotificationService.swift */; }; + 7FD73CA22B23CE9500420AF3 /* NotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 7FD73C9B2B23CE9500420AF3 /* NotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 976CCB5F8C921482E6AEAE71 /* libPods-NewExpensify.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AB40AC8872A3DD6EF53D8B94 /* libPods-NewExpensify.a */; }; BDB853621F354EBB84E619C2 /* ExpensifyNewKansas-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D2AFB39EC1D44BF9B91D3227 /* ExpensifyNewKansas-MediumItalic.otf */; }; DD79042B2792E76D004484B4 /* RCTBootSplash.m in Sources */ = {isa = PBXBuildFile; fileRef = DD79042A2792E76D004484B4 /* RCTBootSplash.m */; }; @@ -34,6 +38,7 @@ E51DC681C7DEE40AEBDDFBFE /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; E9DF872D2525201700607FDC /* AirshipConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = E9DF872C2525201700607FDC /* AirshipConfig.plist */; }; ED222ED90E074A5481A854FA /* ExpensifyNeue-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */; }; + EEAE4F8907465429AA5B5520 /* libPods-NewExpensify.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AEFE6CD54912D427D19133C7 /* libPods-NewExpensify.a */; }; F0C450EA2705020500FD2970 /* colors.json in Resources */ = {isa = PBXBuildFile; fileRef = F0C450E92705020500FD2970 /* colors.json */; }; FF941A8D48F849269AB85C9A /* ExpensifyNewKansas-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 44BF435285B94E5B95F90994 /* ExpensifyNewKansas-Medium.otf */; }; /* End PBXBuildFile section */ @@ -46,8 +51,29 @@ remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = NewExpensify; }; + 7FD73CA02B23CE9500420AF3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7FD73C9A2B23CE9500420AF3; + remoteInfo = NotificationServiceExtension; + }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 7FD73CA32B23CE9500420AF3 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 7FD73CA22B23CE9500420AF3 /* NotificationServiceExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* NewExpensifyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NewExpensifyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -63,7 +89,12 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NewExpensify/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NewExpensify/main.m; sourceTree = ""; }; 18D050DF262400AF000D658B /* BridgingFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgingFile.swift; sourceTree = ""; }; + 1A997AA8204EA3D90907FA80 /* libPods-NotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DDE5449979A136852B939B5 /* Pods-NewExpensify.release adhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release adhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release adhoc.xcconfig"; sourceTree = ""; }; + 25A4587E168FD67CF890B448 /* Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig"; sourceTree = ""; }; + 30FFBD291B71222A393D9CC9 /* Pods-NewExpensify.releasedevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releasedevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releasedevelopment.xcconfig"; sourceTree = ""; }; 32181F72DC539FFD1D1F0CA4 /* Pods-NewExpensify.releaseproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releaseproduction.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releaseproduction.xcconfig"; sourceTree = ""; }; + 34A8FDD1F9AA58B8F15C8380 /* Pods-NewExpensify.release production.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release production.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release production.xcconfig"; sourceTree = ""; }; 374FB8D528A133A7000D84EF /* OriginImageRequestHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OriginImageRequestHandler.h; path = NewExpensify/OriginImageRequestHandler.h; sourceTree = ""; }; 374FB8D628A133FE000D84EF /* OriginImageRequestHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = OriginImageRequestHandler.mm; path = NewExpensify/OriginImageRequestHandler.mm; sourceTree = ""; }; 3BBA44B891E03FAB8255E6F1 /* Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig"; sourceTree = ""; }; @@ -76,26 +107,48 @@ 7041848326A8E40900E09F4D /* RCTStartupTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RCTStartupTimer.h; path = NewExpensify/RCTStartupTimer.h; sourceTree = ""; }; 7041848426A8E47D00E09F4D /* RCTStartupTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RCTStartupTimer.m; path = NewExpensify/RCTStartupTimer.m; sourceTree = ""; }; 70CF6E81262E297300711ADC /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = NewExpensify/BootSplash.storyboard; sourceTree = ""; }; + 75CABB0D0ABB0082FE0EB600 /* Pods-NewExpensify.release staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release staging.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release staging.xcconfig"; sourceTree = ""; }; 76BE68DA894BB75DDFE278DC /* Pods-NewExpensify.releasedevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releasedevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releasedevelopment.xcconfig"; sourceTree = ""; }; 7B318CF669A0F7FE948D5CED /* Pods-NewExpensify.debugadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debugadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debugadhoc.xcconfig"; sourceTree = ""; }; + 7F9DD8D92B2A445B005E3AFA /* ExpError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpError.swift; sourceTree = ""; }; + 7FD73C9B2B23CE9500420AF3 /* NotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 7FD73C9D2B23CE9500420AF3 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + 7FD73C9F2B23CE9500420AF3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8709DF3C8D91F0FC1581CDD7 /* Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig"; sourceTree = ""; }; 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = ""; }; + 8D3B36BF88E773E3C1A383FA /* Pods-NewExpensify.debug staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug staging.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug staging.xcconfig"; sourceTree = ""; }; + 90E08F0C8C924EDA018C8866 /* Pods-NotificationServiceExtension.releaseproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.releaseproduction.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.releaseproduction.xcconfig"; sourceTree = ""; }; + 96552D489D9F09B6A5ABD81B /* Pods-NewExpensify-NewExpensifyTests.release production.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release production.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release production.xcconfig"; sourceTree = ""; }; AB40AC8872A3DD6EF53D8B94 /* libPods-NewExpensify.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + AEFE6CD54912D427D19133C7 /* libPods-NewExpensify.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify.a"; sourceTree = BUILT_PRODUCTS_DIR; }; BCD444BEDDB0AF1745B39049 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NewExpensify-NewExpensifyTests/ExpoModulesProvider.swift"; sourceTree = ""; }; + BD6E1BA27D6ABE0AC9D70586 /* Pods-NewExpensify-NewExpensifyTests.release development.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release development.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release development.xcconfig"; sourceTree = ""; }; + BD8828A882E2D6B51362AAC3 /* Pods-NewExpensify.releaseadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releaseadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releaseadhoc.xcconfig"; sourceTree = ""; }; BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = ""; }; C3788801E65E896FA7C77298 /* Pods-NewExpensify.debugproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debugproduction.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debugproduction.xcconfig"; sourceTree = ""; }; + C3FF914C045A138C061D306E /* Pods-NotificationServiceExtension.debugproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.debugproduction.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.debugproduction.xcconfig"; sourceTree = ""; }; + CE2F84BEE9A6DCC228AF7E42 /* Pods-NewExpensify.debugproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debugproduction.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debugproduction.xcconfig"; sourceTree = ""; }; + CECC4CBB97A55705A33BEA9E /* Pods-NewExpensify.debug development.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug development.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug development.xcconfig"; sourceTree = ""; }; D2AFB39EC1D44BF9B91D3227 /* ExpensifyNewKansas-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-MediumItalic.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-MediumItalic.otf"; sourceTree = ""; }; + D3F458C994019E6A571461B7 /* Pods-NotificationServiceExtension.debugadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.debugadhoc.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.debugadhoc.xcconfig"; sourceTree = ""; }; + DB76E0D5C670190A0997C71E /* Pods-NewExpensify-NewExpensifyTests.debug production.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug production.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug production.xcconfig"; sourceTree = ""; }; DCF33E34FFEC48128CDD41D4 /* ExpensifyMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Bold.otf"; path = "../assets/fonts/native/ExpensifyMono-Bold.otf"; sourceTree = ""; }; DD7904292792E76D004484B4 /* RCTBootSplash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTBootSplash.h; path = NewExpensify/RCTBootSplash.h; sourceTree = ""; }; DD79042A2792E76D004484B4 /* RCTBootSplash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTBootSplash.m; path = NewExpensify/RCTBootSplash.m; sourceTree = ""; }; + E2C8555C607612465A7473F8 /* Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig"; sourceTree = ""; }; + E2F1036F70CBFE39E9352674 /* Pods-NewExpensify-NewExpensifyTests.debug development.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug development.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug development.xcconfig"; sourceTree = ""; }; E2F78D2A9B3DB96F0524690B /* Pods-NewExpensify-NewExpensifyTests.releaseproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.releaseproduction.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.releaseproduction.xcconfig"; sourceTree = ""; }; + E61AD6D2DE65B6FB14945CDF /* Pods-NotificationServiceExtension.releaseadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.releaseadhoc.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.releaseadhoc.xcconfig"; sourceTree = ""; }; E681F80D97E6E4BB26194246 /* Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig"; sourceTree = ""; }; E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Regular.otf"; path = "../assets/fonts/native/ExpensifyMono-Regular.otf"; sourceTree = ""; }; E9DF872C2525201700607FDC /* AirshipConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AirshipConfig.plist; sourceTree = ""; }; EA58D43E81BC49541F7FC7E7 /* Pods-NewExpensify.debugdevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debugdevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debugdevelopment.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; + F082D95EE104912B48EA98BA /* Pods-NotificationServiceExtension.releasedevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.releasedevelopment.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.releasedevelopment.xcconfig"; sourceTree = ""; }; F0C450E92705020500FD2970 /* colors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = colors.json; path = ../colors.json; sourceTree = ""; }; F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; + FBEBA6FBED49FB41D6F93896 /* Pods-NotificationServiceExtension.debugdevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.debugdevelopment.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.debugdevelopment.xcconfig"; sourceTree = ""; }; FF0EADDA6099EF76253FA7AB /* Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -114,6 +167,16 @@ files = ( E51DC681C7DEE40AEBDDFBFE /* BuildFile in Frameworks */, 976CCB5F8C921482E6AEAE71 /* libPods-NewExpensify.a in Frameworks */, + E51DC681C7DEE40AEBDDFBFE /* BuildFile in Frameworks */, + EEAE4F8907465429AA5B5520 /* libPods-NewExpensify.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7FD73C982B23CE9500420AF3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 059DC4EFD39EF39437E6823D /* libPods-NotificationServiceExtension.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -159,6 +222,8 @@ children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED2971642150620600B7C4FE /* JavaScriptCore.framework */, + AEFE6CD54912D427D19133C7 /* libPods-NewExpensify.a */, + 1A997AA8204EA3D90907FA80 /* libPods-NotificationServiceExtension.a */, AB40AC8872A3DD6EF53D8B94 /* libPods-NewExpensify.a */, 076FD9E41E08971BBF51D580 /* libPods-NewExpensify-NewExpensifyTests.a */, ); @@ -182,6 +247,16 @@ name = ExpoModulesProviders; sourceTree = ""; }; + 7FD73C9C2B23CE9500420AF3 /* NotificationServiceExtension */ = { + isa = PBXGroup; + children = ( + 7FD73C9D2B23CE9500420AF3 /* NotificationService.swift */, + 7FD73C9F2B23CE9500420AF3 /* Info.plist */, + 7F9DD8D92B2A445B005E3AFA /* ExpError.swift */, + ); + path = NotificationServiceExtension; + sourceTree = ""; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( @@ -203,6 +278,7 @@ 13B07FAE1A68108700A75B9A /* NewExpensify */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* NewExpensifyTests */, + 7FD73C9C2B23CE9500420AF3 /* NotificationServiceExtension */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, EC29677F0A49C2946A495A33 /* Pods */, @@ -219,6 +295,7 @@ children = ( 13B07F961A680F5B00A75B9A /* New Expensify Dev.app */, 00E356EE1AD99517003FC87E /* NewExpensifyTests.xctest */, + 7FD73C9B2B23CE9500420AF3 /* NotificationServiceExtension.appex */, ); name = Products; sourceTree = ""; @@ -249,6 +326,27 @@ EC29677F0A49C2946A495A33 /* Pods */ = { isa = PBXGroup; children = ( + CECC4CBB97A55705A33BEA9E /* Pods-NewExpensify.debug development.xcconfig */, + 8D3B36BF88E773E3C1A383FA /* Pods-NewExpensify.debug staging.xcconfig */, + 1DDE5449979A136852B939B5 /* Pods-NewExpensify.release adhoc.xcconfig */, + 75CABB0D0ABB0082FE0EB600 /* Pods-NewExpensify.release staging.xcconfig */, + 34A8FDD1F9AA58B8F15C8380 /* Pods-NewExpensify.release production.xcconfig */, + E2F1036F70CBFE39E9352674 /* Pods-NewExpensify-NewExpensifyTests.debug development.xcconfig */, + DB76E0D5C670190A0997C71E /* Pods-NewExpensify-NewExpensifyTests.debug production.xcconfig */, + BD6E1BA27D6ABE0AC9D70586 /* Pods-NewExpensify-NewExpensifyTests.release development.xcconfig */, + 96552D489D9F09B6A5ABD81B /* Pods-NewExpensify-NewExpensifyTests.release production.xcconfig */, + CE2F84BEE9A6DCC228AF7E42 /* Pods-NewExpensify.debugproduction.xcconfig */, + 30FFBD291B71222A393D9CC9 /* Pods-NewExpensify.releasedevelopment.xcconfig */, + BD8828A882E2D6B51362AAC3 /* Pods-NewExpensify.releaseadhoc.xcconfig */, + 8709DF3C8D91F0FC1581CDD7 /* Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig */, + 25A4587E168FD67CF890B448 /* Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig */, + E2C8555C607612465A7473F8 /* Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig */, + FBEBA6FBED49FB41D6F93896 /* Pods-NotificationServiceExtension.debugdevelopment.xcconfig */, + D3F458C994019E6A571461B7 /* Pods-NotificationServiceExtension.debugadhoc.xcconfig */, + C3FF914C045A138C061D306E /* Pods-NotificationServiceExtension.debugproduction.xcconfig */, + F082D95EE104912B48EA98BA /* Pods-NotificationServiceExtension.releasedevelopment.xcconfig */, + E61AD6D2DE65B6FB14945CDF /* Pods-NotificationServiceExtension.releaseadhoc.xcconfig */, + 90E08F0C8C924EDA018C8866 /* Pods-NotificationServiceExtension.releaseproduction.xcconfig */, EA58D43E81BC49541F7FC7E7 /* Pods-NewExpensify.debugdevelopment.xcconfig */, 7B318CF669A0F7FE948D5CED /* Pods-NewExpensify.debugadhoc.xcconfig */, C3788801E65E896FA7C77298 /* Pods-NewExpensify.debugproduction.xcconfig */, @@ -298,6 +396,7 @@ FD10A7F022414F080027D42C /* Start Packager */, 5CF45ABA52C0BB0D7B9D139A /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, + 7FD73CA32B23CE9500420AF3 /* Embed Foundation Extensions */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, @@ -309,18 +408,38 @@ buildRules = ( ); dependencies = ( + 7FD73CA12B23CE9500420AF3 /* PBXTargetDependency */, ); name = NewExpensify; productName = NewExpensify; productReference = 13B07F961A680F5B00A75B9A /* New Expensify Dev.app */; productType = "com.apple.product-type.application"; }; + 7FD73C9A2B23CE9500420AF3 /* NotificationServiceExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7FD73CAA2B23CE9500420AF3 /* Build configuration list for PBXNativeTarget "NotificationServiceExtension" */; + buildPhases = ( + F3D35ED760B830954BD8A7BB /* [CP] Check Pods Manifest.lock */, + 7FD73C972B23CE9500420AF3 /* Sources */, + 7FD73C982B23CE9500420AF3 /* Frameworks */, + 7FD73C992B23CE9500420AF3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NotificationServiceExtension; + productName = NotificationServiceExtension; + productReference = 7FD73C9B2B23CE9500420AF3 /* NotificationServiceExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1500; LastUpgradeCheck = 1130; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -334,6 +453,11 @@ LastSwiftMigration = 1230; ProvisioningStyle = Manual; }; + 7FD73C9A2B23CE9500420AF3 = { + CreatedOnToolsVersion = 15.0.1; + DevelopmentTeam = 368M544MTT; + ProvisioningStyle = Manual; + }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NewExpensify" */; @@ -351,6 +475,7 @@ targets = ( 13B07F861A680F5B00A75B9A /* NewExpensify */, 00E356ED1AD99517003FC87E /* NewExpensifyTests */, + 7FD73C9A2B23CE9500420AF3 /* NotificationServiceExtension */, ); }; /* End PBXProject section */ @@ -384,6 +509,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7FD73C992B23CE9500420AF3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -616,6 +748,28 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewExpensify/Pods-NewExpensify-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + F3D35ED760B830954BD8A7BB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-NotificationServiceExtension-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; F6E16E41F88F567A8CDD037C /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -694,6 +848,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7FD73C972B23CE9500420AF3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7F9DD8DA2B2A445B005E3AFA /* ExpError.swift in Sources */, + 7FD73C9E2B23CE9500420AF3 /* NotificationService.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -702,6 +865,11 @@ target = 13B07F861A680F5B00A75B9A /* NewExpensify */; targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; }; + 7FD73CA12B23CE9500420AF3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7FD73C9A2B23CE9500420AF3 /* NotificationServiceExtension */; + targetProxy = 7FD73CA02B23CE9500420AF3 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -739,7 +907,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = E681F80D97E6E4BB26194246 /* Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; @@ -772,9 +939,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NewExpensify/Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; ENABLE_BITCODE = NO; INFOPLIST_FILE = "$(SRCROOT)/NewExpensify/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; @@ -791,7 +960,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.dev; PRODUCT_NAME = "New Expensify Dev"; - PROVISIONING_PROFILE_SPECIFIER = expensify_chat_dev; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) Development"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -808,9 +978,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NewExpensify/Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; INFOPLIST_FILE = NewExpensify/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -826,13 +998,519 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.dev; PRODUCT_NAME = "New Expensify Dev"; - PROVISIONING_PROFILE_SPECIFIER = expensify_chat_dev; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) Development"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = ReleaseDevelopment; }; + 7FD73CA42B23CE9500420AF3 /* DebugDevelopment */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FBEBA6FBED49FB41D6F93896 /* Pods-NotificationServiceExtension.debugdevelopment.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; + PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.dev.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) Development: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugDevelopment; + }; + 7FD73CA52B23CE9500420AF3 /* DebugAdHoc */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D3F458C994019E6A571461B7 /* Pods-NotificationServiceExtension.debugadhoc.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; + PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.adhoc.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AdHoc: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugAdHoc; + }; + 7FD73CA62B23CE9500420AF3 /* DebugProduction */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C3FF914C045A138C061D306E /* Pods-NotificationServiceExtension.debugproduction.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; + PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) Development: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugProduction; + }; + 7FD73CA72B23CE9500420AF3 /* ReleaseDevelopment */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F082D95EE104912B48EA98BA /* Pods-NotificationServiceExtension.releasedevelopment.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; + PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.dev.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) Development: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = ReleaseDevelopment; + }; + 7FD73CA82B23CE9500420AF3 /* ReleaseAdHoc */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E61AD6D2DE65B6FB14945CDF /* Pods-NotificationServiceExtension.releaseadhoc.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; + PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.adhoc.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AdHoc: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = ReleaseAdHoc; + }; + 7FD73CA92B23CE9500420AF3 /* ReleaseProduction */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 90E08F0C8C924EDA018C8866 /* Pods-NotificationServiceExtension.releaseproduction.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = NotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = NotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; + PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat.NotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AppStore: Notification Service"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = ReleaseProduction; + }; 83CBBA201A601CBA00E9B192 /* DebugDevelopment */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1043,6 +1721,7 @@ CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; ENABLE_BITCODE = NO; INFOPLIST_FILE = "$(SRCROOT)/NewExpensify/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; @@ -1059,7 +1738,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; - PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) AppStore"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AppStore"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1177,6 +1857,7 @@ CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; ENABLE_BITCODE = NO; INFOPLIST_FILE = "$(SRCROOT)/NewExpensify/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; @@ -1193,7 +1874,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.adhoc; PRODUCT_NAME = "New Expensify AdHoc"; - PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) AdHoc"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AdHoc"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1305,6 +1987,7 @@ CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; INFOPLIST_FILE = NewExpensify/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1320,7 +2003,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; - PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) AppStore"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AppStore"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; @@ -1429,6 +2113,7 @@ CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; INFOPLIST_FILE = NewExpensify/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -1444,7 +2129,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.expensify.chat.adhoc; PRODUCT_NAME = "New Expensify AdHoc"; - PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; + PROVISIONING_PROFILE_SPECIFIER = "(NewApp) AdHoc"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "(NewApp) AdHoc"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; @@ -1508,6 +2194,19 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = DebugDevelopment; }; + 7FD73CAA2B23CE9500420AF3 /* Build configuration list for PBXNativeTarget "NotificationServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7FD73CA42B23CE9500420AF3 /* DebugDevelopment */, + 7FD73CA52B23CE9500420AF3 /* DebugAdHoc */, + 7FD73CA62B23CE9500420AF3 /* DebugProduction */, + 7FD73CA72B23CE9500420AF3 /* ReleaseDevelopment */, + 7FD73CA82B23CE9500420AF3 /* ReleaseAdHoc */, + 7FD73CA92B23CE9500420AF3 /* ReleaseProduction */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = DebugDevelopment; + }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NewExpensify" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/NewExpensify/Chat.entitlements b/ios/NewExpensify/Chat.entitlements index 5300e35eadbf..165745a3c1a0 100644 --- a/ios/NewExpensify/Chat.entitlements +++ b/ios/NewExpensify/Chat.entitlements @@ -14,5 +14,7 @@ applinks:staging.new.expensify.com webcredentials:new.expensify.com + com.apple.developer.usernotifications.communication + diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index c89aa0f1a00f..f267261a49c0 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.17 + 1.4.21 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.17.7 + 1.4.21.1 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes @@ -85,6 +85,10 @@ Your camera roll is used to store chat attachments. NSPhotoLibraryUsageDescription Your photos are used to create chat attachments. + NSUserActivityTypes + + INSendMessageIntent + UIAppFonts ExpensifyNewKansas-Medium.otf diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index c7e17b965e17..f95a3f871d4c 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.4.17 + 1.4.21 CFBundleSignature ???? CFBundleVersion - 1.4.17.7 + 1.4.21.1 diff --git a/ios/NotificationServiceExtension/ExpError.swift b/ios/NotificationServiceExtension/ExpError.swift new file mode 100644 index 000000000000..147618fb26d9 --- /dev/null +++ b/ios/NotificationServiceExtension/ExpError.swift @@ -0,0 +1,12 @@ +// +// ExpError.swift +// NotificationServiceExtension +// +// Created by Andrew Rosiclair on 12/13/23. +// + +import Foundation + +enum ExpError: Error { + case runtimeError(String) +} diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist new file mode 100644 index 000000000000..57421ebf9b75 --- /dev/null +++ b/ios/NotificationServiceExtension/Info.plist @@ -0,0 +1,13 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/ios/NotificationServiceExtension/NotificationService.swift b/ios/NotificationServiceExtension/NotificationService.swift new file mode 100644 index 000000000000..c4eb01981bf2 --- /dev/null +++ b/ios/NotificationServiceExtension/NotificationService.swift @@ -0,0 +1,239 @@ +// +// NotificationService.swift +// NotificationServiceExtension +// +// Created by Andrew Rosiclair on 12/8/23. +// + +import AirshipServiceExtension +import os.log +import Intents + +class NotificationService: UANotificationServiceExtension { + + var contentHandler: ((UNNotificationContent) -> Void)? + var bestAttemptContent: UNMutableNotificationContent? + let log = OSLog(subsystem: Bundle.main.bundleIdentifier ?? "com.expensify.chat.dev.NotificationServiceExtension", category: "NotificationService") + + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + os_log("[NotificationService] didReceive() - received notification", log: log) + + self.contentHandler = contentHandler + guard let bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) else { + contentHandler(request.content) + return + } + + if #available(iOSApplicationExtension 15.0, *) { + configureCommunicationNotification(notificationContent: bestAttemptContent, contentHandler: contentHandler) + } else { + contentHandler(bestAttemptContent) + } + } + + /** + * Parses the notification content and modifies it to be a Communication Notification. More info here: https://developer.apple.com/documentation/usernotifications/implementing_communication_notifications + */ + @available(iOSApplicationExtension 15.0, *) + func configureCommunicationNotification(notificationContent: UNMutableNotificationContent, contentHandler: @escaping (UNNotificationContent) -> Void) { + var notificationData: NotificationData + do { + notificationData = try parsePayload(notificationContent: notificationContent) + } catch ExpError.runtimeError(let errorMessage) { + os_log("[NotificationService] configureCommunicationNotification() - couldn't parse the payload '%@'", log: log, type: .error, errorMessage) + contentHandler(notificationContent) + return + } catch { + os_log("[NotificationService] configureCommunicationNotification() - unexpected error while parsing payload", log: log, type: .error) + contentHandler(notificationContent) + return + } + + // Create an intent for the incoming communication message + let intent: INSendMessageIntent = createMessageIntent(notificationData: notificationData) + + // Use the intent to initialize the interaction. + let interaction = INInteraction(intent: intent, response: nil) + + + // Interaction direction is incoming because the user is + // receiving this message. + interaction.direction = .incoming + + + // Donate the interaction before updating notification content. + interaction.donate { error in + if error != nil { + os_log("[NotificationService] configureCommunicationNotification() - failed to donate the message intent", log: self.log, type: .error) + contentHandler(notificationContent) + return + } + + // After donation, update the notification content. + do { + // Update notification content before displaying the + // communication notification. + let updatedContent = try notificationContent.updating(from: intent) + + // Call the content handler with the updated content + // to display the communication notification. + contentHandler(updatedContent) + } catch { + os_log("[NotificationService] configureCommunicationNotification() - failed to update the notification with send message intent", log: self.log, type: .error) + contentHandler(notificationContent) + } + } + } + + func parsePayload(notificationContent: UNMutableNotificationContent) throws -> NotificationData { + guard let payload = notificationContent.userInfo["payload"] as? NSDictionary else { + throw ExpError.runtimeError("payload missing") + } + + guard let reportID = payload["reportID"] as? Int64 else { + throw ExpError.runtimeError("payload.reportID missing") + } + + guard let reportActionID = payload["reportActionID"] as? String else { + throw ExpError.runtimeError("payload.reportActionID missing") + } + + guard let onyxData = payload["onyxData"] as? NSArray else { + throw ExpError.runtimeError("payload.onyxData missing" + reportActionID) + } + + guard let reportActionOnyxUpdate = onyxData[1] as? NSDictionary else { + throw ExpError.runtimeError("payload.onyxData[1] missing" + reportActionID) + } + + guard let reportActionCollection = reportActionOnyxUpdate["value"] as? NSDictionary else { + throw ExpError.runtimeError("payload.onyxData[1].value (report action onyx update) missing" + reportActionID) + } + + guard let reportAction = reportActionCollection[reportActionID] as? NSDictionary else { + throw ExpError.runtimeError("payload.onyxData[1].value['\(reportActionID)'] (report action) missing" + reportActionID) + } + + guard let avatarURL = reportAction["avatar"] as? String else { + throw ExpError.runtimeError("reportAction.avatar missing. reportActionID: " + reportActionID) + } + + guard let accountID = reportAction["actorAccountID"] as? Int else { + throw ExpError.runtimeError("reportAction.actorAccountID missing. reportActionID: " + reportActionID) + } + + guard let person = reportAction["person"] as? NSArray else { + throw ExpError.runtimeError("reportAction.person missing. reportActionID: " + reportActionID) + } + + guard let personObject = person[0] as? NSDictionary else { + throw ExpError.runtimeError("reportAction.person[0] missing. reportActionID: " + reportActionID) + } + + guard let userName = personObject["text"] as? String else { + throw ExpError.runtimeError("reportAction.person[0].text missing. reportActionID: " + reportActionID) + } + + return NotificationData( + reportID: reportID, + reportActionID: reportActionID, + avatarURL: avatarURL, + accountID: accountID, + userName: userName, + title: notificationContent.title, + messageText: notificationContent.body, + roomName: payload["roomName"] as? String + ) + } + + @available(iOSApplicationExtension 14.0, *) + func createMessageIntent(notificationData: NotificationData) -> INSendMessageIntent { + // Initialize only the sender for a one-to-one message intent. + let handle = INPersonHandle(value: String(notificationData.accountID), type: .unknown) + let avatar = fetchINImage(imageURL: notificationData.avatarURL, reportActionID: notificationData.reportActionID) + let sender = INPerson(personHandle: handle, + nameComponents: nil, + displayName: notificationData.userName, + image: avatar, + contactIdentifier: nil, + customIdentifier: nil) + + // Configure the group/room name if there is one + var speakableGroupName: INSpeakableString? = nil + var recipients: [INPerson]? = nil + if (notificationData.roomName != nil) { + speakableGroupName = INSpeakableString(spokenPhrase: notificationData.roomName ?? "") + + // To add the group name subtitle there must be multiple recipients set. However, we do not have + // data on the participatns in the room/group chat so we just add a placeholder here. This shouldn't + // appear anywhere in the UI + let placeholderPerson = INPerson(personHandle: INPersonHandle(value: "placeholder", type: .unknown), + nameComponents: nil, + displayName: "placeholder", + image: nil, + contactIdentifier: nil, + customIdentifier: nil) + recipients = [sender, placeholderPerson] + } + + // Because this communication is incoming, you can infer that the current user is + // a recipient. Don't include the current user when initializing the intent. + let intent = INSendMessageIntent(recipients: recipients, + outgoingMessageType: .outgoingMessageText, + content: notificationData.messageText, + speakableGroupName: speakableGroupName, + conversationIdentifier: String(notificationData.reportID), + serviceName: nil, + sender: sender, + attachments: nil) + + // If the group name is set, we force the avatar to just be the sender's avatar + intent.setImage(avatar, forParameterNamed: \.speakableGroupName) + + return intent + } + + override func serviceExtensionTimeWillExpire() { + // Called just before the extension will be terminated by the system. + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + contentHandler(bestAttemptContent) + } + } + + func fetchINImage(imageURL: String, reportActionID: String) -> INImage? { + guard let url = URL(string: imageURL) else { + return nil + } + + do { + let data = try Data(contentsOf: url) + return INImage(imageData: data) + } catch { + os_log("[NotificationService] fetchINImage() - failed to fetch avatar. reportActionID: %@", log: self.log, type: .error, reportActionID) + return nil + } + } +} + +class NotificationData { + public var reportID: Int64 + public var reportActionID: String + public var avatarURL: String + public var accountID: Int + public var userName: String + public var title: String + public var messageText: String + public var roomName: String? + + public init (reportID: Int64, reportActionID: String, avatarURL: String, accountID: Int, userName: String, title: String, messageText: String, roomName: String?) { + self.reportID = reportID + self.reportActionID = reportActionID + self.avatarURL = avatarURL + self.accountID = accountID + self.userName = userName + self.title = title + self.messageText = messageText + self.roomName = roomName + } +} diff --git a/ios/Podfile b/ios/Podfile index 307e2c46108c..c12596d3191e 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -129,3 +129,7 @@ target 'NewExpensify' do end end end + +target 'NotificationServiceExtension' do + pod 'AirshipServiceExtension' +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a19ea5b77df0..77c390c46416 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -20,6 +20,7 @@ PODS: - Airship (= 16.12.1) - Airship/MessageCenter (= 16.12.1) - Airship/PreferenceCenter (= 16.12.1) + - AirshipServiceExtension (16.12.5) - AppAuth (1.6.2): - AppAuth/Core (= 1.6.2) - AppAuth/ExternalUserAgent (= 1.6.2) @@ -801,35 +802,10 @@ PODS: - React-Core - RNReactNativeHapticFeedback (1.14.0): - React-Core - - RNReanimated (3.5.4): - - DoubleConversion - - FBLazyVector - - glog - - hermes-engine - - RCT-Folly - - RCTRequired - - RCTTypeSafety - - React-callinvoker + - RNReanimated (3.6.1): + - RCT-Folly (= 2021.07.22.00) - React-Core - - React-Core/DevSupport - - React-Core/RCTWebSocket - - React-CoreModules - - React-cxxreact - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-RCTActionSheet - - React-RCTAnimation - - React-RCTAppDelegate - - React-RCTBlob - - React-RCTImage - - React-RCTLinking - - React-RCTNetwork - - React-RCTSettings - - React-RCTText - ReactCommon/turbomodule/core - - Yoga - RNScreens (3.21.0): - React-Core - React-RCTImage @@ -857,6 +833,7 @@ PODS: - Yoga (~> 1.14) DEPENDENCIES: + - AirshipServiceExtension - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) @@ -974,6 +951,7 @@ SPEC REPOS: trunk: - Airship - AirshipFrameworkProxy + - AirshipServiceExtension - AppAuth - CocoaAsyncSocket - Firebase @@ -1205,6 +1183,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Airship: 2f4510b497a8200780752a5e0304a9072bfffb6d AirshipFrameworkProxy: ea1b6c665c798637b93c465b5e505be3011f1d9d + AirshipServiceExtension: 89c6e25a69f3458d9dbd581c700cffb196b61930 AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570 boost: 57d2868c099736d80fcd648bf211b4431e51a558 BVLinearGradient: 421743791a59d259aec53f4c58793aad031da2ca @@ -1329,7 +1308,7 @@ SPEC CHECKSUMS: rnmapbox-maps: 6f638ec002aa6e906a6f766d69cd45f968d98e64 RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c - RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87 + RNReanimated: fdbaa9c964bbab7fac50c90862b6cc5f041679b9 RNScreens: d037903436160a4b039d32606668350d2a808806 RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 @@ -1342,6 +1321,6 @@ SPEC CHECKSUMS: Yoga: 3efc43e0d48686ce2e8c60f99d4e6bd349aff981 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: bfe134fd8d3bb1d9232f59a7601623c7193bca3e +PODFILE CHECKSUM: c403784ee1fdf281bcc552696504207f3022cb66 COCOAPODS: 1.12.1 diff --git a/ios/chat_expensify_appstore.mobileprovision.gpg b/ios/chat_expensify_appstore.mobileprovision.gpg deleted file mode 100644 index 246f5f0ec99e..000000000000 Binary files a/ios/chat_expensify_appstore.mobileprovision.gpg and /dev/null differ diff --git a/ios/expensify_chat_adhoc.mobileprovision.gpg b/ios/expensify_chat_adhoc.mobileprovision.gpg deleted file mode 100644 index f4691df10d67..000000000000 Binary files a/ios/expensify_chat_adhoc.mobileprovision.gpg and /dev/null differ diff --git a/package-lock.json b/package-lock.json index af50c41dcb0a..c8b4b2ba2082 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.17-7", + "version": "1.4.21-1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.17-7", + "version": "1.4.21-1", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -103,7 +103,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "3.5.4", + "react-native-reanimated": "^3.6.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.4.1", "react-native-screens": "3.21.0", @@ -199,7 +199,7 @@ "electron-builder": "24.6.4", "eslint": "^7.6.0", "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-expensify": "^2.0.42", + "eslint-config-expensify": "^2.0.43", "eslint-config-prettier": "^8.8.0", "eslint-plugin-jest": "^24.1.0", "eslint-plugin-jsdoc": "^46.2.6", @@ -29995,9 +29995,9 @@ } }, "node_modules/eslint-config-expensify": { - "version": "2.0.42", - "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.42.tgz", - "integrity": "sha512-TNwbfIGjOp4EjT6HKEpp10mr6dkBNCNMTeMmpuQyS0Nqv1tRGJltoU3GFmUHJywrLkEmu21iC0NNMmoJ1XzmLg==", + "version": "2.0.43", + "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.43.tgz", + "integrity": "sha512-kLd6NyYbyb3mCB6VH6vu49/RllwNo0rdXcLUUGB7JGny+2N19jOmBJ4/GLKsbpFzvEZEghXfn7BITPRkxVJcgg==", "dev": true, "dependencies": { "@lwc/eslint-plugin-lwc": "^0.11.0", @@ -47677,9 +47677,9 @@ } }, "node_modules/react-native-reanimated": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.5.4.tgz", - "integrity": "sha512-8we9LLDO1o4Oj9/DICeEJ2K1tjfqkJagqQUglxeUAkol/HcEJ6PGxIrpBcNryLqCDYEcu6FZWld/FzizBIw6bg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.1.tgz", + "integrity": "sha512-F4vG9Yf9PKmE3GaWtVGUpzj3SM6YY2cx1yRHCwiMd1uY7W0gU017LfcVUorboJnj0y5QZqEriEK1Usq2Y8YZqg==", "dependencies": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", @@ -78014,9 +78014,9 @@ } }, "eslint-config-expensify": { - "version": "2.0.42", - "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.42.tgz", - "integrity": "sha512-TNwbfIGjOp4EjT6HKEpp10mr6dkBNCNMTeMmpuQyS0Nqv1tRGJltoU3GFmUHJywrLkEmu21iC0NNMmoJ1XzmLg==", + "version": "2.0.43", + "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.43.tgz", + "integrity": "sha512-kLd6NyYbyb3mCB6VH6vu49/RllwNo0rdXcLUUGB7JGny+2N19jOmBJ4/GLKsbpFzvEZEghXfn7BITPRkxVJcgg==", "dev": true, "requires": { "@lwc/eslint-plugin-lwc": "^0.11.0", @@ -90489,9 +90489,9 @@ "requires": {} }, "react-native-reanimated": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.5.4.tgz", - "integrity": "sha512-8we9LLDO1o4Oj9/DICeEJ2K1tjfqkJagqQUglxeUAkol/HcEJ6PGxIrpBcNryLqCDYEcu6FZWld/FzizBIw6bg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.1.tgz", + "integrity": "sha512-F4vG9Yf9PKmE3GaWtVGUpzj3SM6YY2cx1yRHCwiMd1uY7W0gU017LfcVUorboJnj0y5QZqEriEK1Usq2Y8YZqg==", "requires": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", diff --git a/package.json b/package.json index f48b1e0fda2e..bd4b8ffacedf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.17-7", + "version": "1.4.21-1", "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.", @@ -151,7 +151,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "3.5.4", + "react-native-reanimated": "^3.6.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.4.1", "react-native-screens": "3.21.0", @@ -247,7 +247,7 @@ "electron-builder": "24.6.4", "eslint": "^7.6.0", "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-expensify": "^2.0.42", + "eslint-config-expensify": "^2.0.43", "eslint-config-prettier": "^8.8.0", "eslint-plugin-jest": "^24.1.0", "eslint-plugin-jsdoc": "^46.2.6", diff --git a/src/CONST.ts b/src/CONST.ts index 3527902dff40..cd4b4f693fa0 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -549,6 +549,7 @@ const CONST = { INDIVIDUAL_BUDGET_NOTIFICATION: 'POLICYCHANGELOG_INDIVIDUAL_BUDGET_NOTIFICATION', INVITE_TO_ROOM: 'POLICYCHANGELOG_INVITETOROOM', REMOVE_FROM_ROOM: 'POLICYCHANGELOG_REMOVEFROMROOM', + REPLACE_CATEGORIES: 'POLICYCHANGELOG_REPLACE_CATEGORIES', SET_AUTOREIMBURSEMENT: 'POLICYCHANGELOG_SET_AUTOREIMBURSEMENT', SET_AUTO_JOIN: 'POLICYCHANGELOG_SET_AUTO_JOIN', SET_CATEGORY_NAME: 'POLICYCHANGELOG_SET_CATEGORY_NAME', @@ -593,6 +594,7 @@ const CONST = { JOIN_ROOM: 'JOINROOM', }, }, + THREAD_DISABLED: ['CREATED'], }, ARCHIVE_REASON: { DEFAULT: 'default', @@ -717,6 +719,7 @@ const CONST = { TRIE_INITIALIZATION: 'trie_initialization', COMMENT_LENGTH_DEBOUNCE_TIME: 500, SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, + RESIZE_DEBOUNCE_TIME: 100, }, PRIORITY_MODE: { GSD: 'gsd', @@ -820,6 +823,7 @@ const CONST = { MAX_PENDING_TIME_MS: 10 * 1000, MAX_REQUEST_RETRIES: 10, }, + WEEK_STARTS_ON: 1, // Monday DEFAULT_TIME_ZONE: {automatic: true, selected: 'America/Los_Angeles'}, DEFAULT_ACCOUNT_DATA: {errors: null, success: '', isLoading: false}, DEFAULT_CLOSE_ACCOUNT_DATA: {errors: null, success: '', isLoading: false}, @@ -850,7 +854,7 @@ const CONST = { // It's copied here so that the same regex pattern can be used in form validations to be consistent with the server. VALIDATE_FOR_HTML_TAG_REGEX: /<([^>\s]+)(?:[^>]*?)>/g, - VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+[\s\w~!@#$%^&*(){}[\];':"`|?.,/\\+\-=<]+.*[\s]*)>/g, + VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX: /<([\s]+.+[\s]*)>/g, WHITELISTED_TAGS: [/<>/, /< >/, /<->/, /<-->/, /
/, //], @@ -976,6 +980,7 @@ const CONST = { CHAT_FOOTER_SECONDARY_ROW_HEIGHT: 15, CHAT_FOOTER_SECONDARY_ROW_PADDING: 5, CHAT_FOOTER_MIN_HEIGHT: 65, + CHAT_FOOTER_HORIZONTAL_PADDING: 40, CHAT_SKELETON_VIEW: { AVERAGE_ROW_HEIGHT: 80, HEIGHT_FOR_ROW_COUNT: { @@ -1171,6 +1176,7 @@ const CONST = { EXPENSIFY: 'Expensify', VBBA: 'ACH', }, + DEFAULT_AMOUNT: 0, TYPE: { SEND: 'send', SPLIT: 'split', @@ -1296,6 +1302,12 @@ const CONST = { USE_EXPENSIFY_FEES: 'use.expensify.com/fees', }, + LAYOUT_WIDTH: { + WIDE: 'wide', + NARROW: 'narrow', + NONE: 'none', + }, + ICON_TYPE_ICON: 'icon', ICON_TYPE_AVATAR: 'avatar', ICON_TYPE_WORKSPACE: 'workspace', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 8bcbeb6c18d6..90c0114eaa56 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -372,6 +372,12 @@ const ROUTES = { getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => getUrlWithBackToParam(`create/${iouType}/waypoint/${transactionID}/${reportID}/${pageIndex}`, backTo), }, + // This URL is used as a redirect to one of the create tabs below. This is so that we can message users with a link + // straight to those flows without needing to have optimistic transaction and report IDs. + MONEY_REQUEST_START: { + route: 'start/:iouType/:iouRequestType', + getRoute: (iouType: ValueOf, iouRequestType: ValueOf) => `start/${iouType}/${iouRequestType}` as const, + }, MONEY_REQUEST_CREATE_TAB_DISTANCE: { route: 'create/:iouType/start/:transactionID/:reportID/distance', getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/distance` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 2cd263237866..c1d2059cd3b0 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -118,6 +118,7 @@ const SCREENS = { DISTANCE_TAB: 'distance', CREATE: 'Money_Request_Create', STEP_CONFIRMATION: 'Money_Request_Step_Confirmation', + START: 'Money_Request_Start', STEP_AMOUNT: 'Money_Request_Step_Amount', STEP_CATEGORY: 'Money_Request_Step_Category', STEP_CURRENCY: 'Money_Request_Step_Currency', diff --git a/src/components/AddressSearch/index.js b/src/components/AddressSearch/index.js index d9e4ef2c0f6e..31b04a3d954f 100644 --- a/src/components/AddressSearch/index.js +++ b/src/components/AddressSearch/index.js @@ -111,6 +111,9 @@ const propTypes = { /** Information about the network */ network: networkPropTypes.isRequired, + /** Location bias for querying search results. */ + locationBias: PropTypes.string, + ...withLocalizePropTypes, }; @@ -138,6 +141,7 @@ const defaultProps = { maxInputLength: undefined, predefinedPlaces: [], resultTypes: 'address', + locationBias: undefined, }; function AddressSearch({ @@ -162,6 +166,7 @@ function AddressSearch({ shouldSaveDraft, translate, value, + locationBias, }) { const theme = useTheme(); const styles = useThemeStyles(); @@ -179,11 +184,11 @@ function AddressSearch({ language: preferredLocale, types: resultTypes, components: isLimitedToUSA ? 'country:us' : undefined, + ...(locationBias && {locationbias: locationBias}), }), - [preferredLocale, resultTypes, isLimitedToUSA], + [preferredLocale, resultTypes, isLimitedToUSA, locationBias], ); const shouldShowCurrentLocationButton = canUseCurrentLocation && searchValue.trim().length === 0 && isFocused; - const saveLocationDetails = (autocompleteData, details) => { const addressComponents = details.address_components; if (!addressComponents) { @@ -192,7 +197,7 @@ function AddressSearch({ // amount of data massaging needs to happen for what the parent expects to get from this function. if (_.size(details)) { onPress({ - address: lodashGet(details, 'description'), + address: autocompleteData.description || lodashGet(details, 'description', ''), lat: lodashGet(details, 'geometry.location.lat', 0), lng: lodashGet(details, 'geometry.location.lng', 0), name: lodashGet(details, 'name'), @@ -261,7 +266,7 @@ function AddressSearch({ lat: lodashGet(details, 'geometry.location.lat', 0), lng: lodashGet(details, 'geometry.location.lng', 0), - address: lodashGet(details, 'formatted_address', ''), + address: autocompleteData.description || lodashGet(details, 'formatted_address', ''), }; // If the address is not in the US, use the full length state name since we're displaying the address's diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 8604d20130c7..2dae84106971 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -30,14 +30,14 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}} const originalMessage = reportClosedAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED ? reportClosedAction.originalMessage : null; const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT; - let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]?.displayName); + let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]); let oldDisplayName: string | undefined; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { const newAccountID = originalMessage?.newAccountID; const oldAccountID = originalMessage?.oldAccountID; - displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]?.displayName); - oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]?.displayName); + displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[newAccountID ?? 0]); + oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[oldAccountID ?? 0]); } const shouldRenderHTML = archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT; diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index 863e59aa4474..51912c04eb31 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -358,6 +358,14 @@ function AttachmentModal(props) { setIsModalOpen(true); }, []); + useEffect(() => { + setSource(props.source); + }, [props.source]); + + useEffect(() => { + setIsAuthTokenRequired(props.isAuthTokenRequired); + }, [props.isAuthTokenRequired]); + const sourceForAttachmentView = props.source || source; const threeDotsMenuItems = useMemo(() => { @@ -368,7 +376,7 @@ function AttachmentModal(props) { const parentReportAction = props.parentReportActions[props.report.parentReportActionID]; const canEdit = - ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT) && + ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, props.parentReport.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT, props.transaction) && !TransactionUtils.isDistanceRequest(props.transaction); if (canEdit) { menuItems.push({ @@ -396,7 +404,7 @@ function AttachmentModal(props) { } return menuItems; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file]); + }, [props.isReceiptAttachment, props.parentReport, props.parentReportActions, props.policy, props.transaction, file, source]); // There are a few things that shouldn't be set until we absolutely know if the file is a receipt or an attachment. // props.isReceiptAttachment will be null until its certain what the file is, in which case it will then be true|false. diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index c01843c7bcb3..b0060afdb813 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -146,6 +146,7 @@ function AttachmentView({ onLoadComplete={() => !loadComplete && setLoadComplete(true)} errorLabelStyles={isUsedInAttachmentModal ? [styles.textLabel, styles.textLarge] : [styles.cursorAuto]} style={isUsedInAttachmentModal ? styles.imageModalPDF : styles.flex1} + isUsedInCarousel={isUsedInCarousel} /> ); diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index c2320f7c0202..b72662f989dc 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -1,5 +1,5 @@ import {FlashList} from '@shopify/flash-list'; -import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useRef} from 'react'; +import React, {ForwardedRef, forwardRef, ReactElement, useCallback, useEffect, useMemo, useRef} from 'react'; import {View} from 'react-native'; // We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another import {ScrollView} from 'react-native-gesture-handler'; @@ -8,6 +8,8 @@ import ColorSchemeWrapper from '@components/ColorSchemeWrapper'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import viewForwardedRef from '@src/types/utils/viewForwardedRef'; import type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps} from './types'; @@ -39,6 +41,7 @@ function BaseAutoCompleteSuggestions( }: AutoCompleteSuggestionsProps, ref: ForwardedRef, ) { + const {windowWidth, isLargeScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const rowHeight = useSharedValue(0); @@ -64,7 +67,13 @@ function BaseAutoCompleteSuggestions( const innerHeight = CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length; const animatedStyles = useAnimatedStyle(() => StyleUtils.getAutoCompleteSuggestionContainerStyle(rowHeight.value)); - + const estimatedListSize = useMemo( + () => ({ + height: CONST.AUTO_COMPLETE_SUGGESTER.SUGGESTION_ROW_HEIGHT * suggestions.length, + width: (isLargeScreenWidth ? windowWidth - variables.sideBarWidth : windowWidth) - CONST.CHAT_FOOTER_HORIZONTAL_PADDING, + }), + [isLargeScreenWidth, suggestions.length, windowWidth], + ); useEffect(() => { rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length, isSuggestionPickerLarge), { duration: 100, @@ -88,6 +97,7 @@ function BaseAutoCompleteSuggestions( | ImageSourcePropType; /** Color for the icon (should be from theme) */ - iconColor: PropTypes.string, + iconColor?: string; /** Title message below the icon */ - title: PropTypes.string.isRequired, + title: string; /** Subtitle message below the title */ - subtitle: PropTypes.string, + subtitle?: string; /** Link message below the subtitle */ - linkKey: PropTypes.string, + linkKey?: TranslationPaths; /** Whether we should show a link to navigate elsewhere */ - shouldShowLink: PropTypes.bool, + shouldShowLink?: boolean; /** The custom icon width */ - iconWidth: PropTypes.number, + iconWidth?: number; /** The custom icon height */ - iconHeight: PropTypes.number, + iconHeight?: number; /** Function to call when pressing the navigation link */ - onLinkPress: PropTypes.func, + onLinkPress?: () => void; /** Whether we should embed the link with subtitle */ - shouldEmbedLinkWithSubtitle: PropTypes.bool, + shouldEmbedLinkWithSubtitle?: boolean; }; -const defaultProps = { - iconColor: null, - subtitle: '', - shouldShowLink: false, - linkKey: 'notFound.goBackHome', - iconWidth: variables.iconSizeSuperLarge, - iconHeight: variables.iconSizeSuperLarge, - onLinkPress: () => Navigation.dismissModal(), - shouldEmbedLinkWithSubtitle: false, -}; - -function BlockingView(props) { +function BlockingView({ + icon, + iconColor, + title, + subtitle = '', + linkKey = 'notFound.goBackHome', + shouldShowLink = false, + iconWidth = variables.iconSizeSuperLarge, + iconHeight = variables.iconSizeSuperLarge, + onLinkPress = () => Navigation.dismissModal(), + shouldEmbedLinkWithSubtitle = false, +}: BlockingViewProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); function renderContent() { @@ -62,14 +62,14 @@ function BlockingView(props) { <> - {props.shouldShowLink ? ( + {shouldShowLink ? ( - {translate(props.linkKey)} + {translate(linkKey)} ) : null} @@ -79,14 +79,14 @@ function BlockingView(props) { return ( - {props.title} + {title} - {props.shouldEmbedLinkWithSubtitle ? ( + {shouldEmbedLinkWithSubtitle ? ( {renderContent()} ) : ( {renderContent()} @@ -95,8 +95,6 @@ function BlockingView(props) { ); } -BlockingView.propTypes = propTypes; -BlockingView.defaultProps = defaultProps; BlockingView.displayName = 'BlockingView'; export default BlockingView; diff --git a/src/components/BlockingViews/FullPageNotFoundView.js b/src/components/BlockingViews/FullPageNotFoundView.tsx similarity index 69% rename from src/components/BlockingViews/FullPageNotFoundView.js rename to src/components/BlockingViews/FullPageNotFoundView.tsx index ce76b96c0eb0..6d7f838bf6c2 100644 --- a/src/components/BlockingViews/FullPageNotFoundView.js +++ b/src/components/BlockingViews/FullPageNotFoundView.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -7,54 +6,54 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import variables from '@styles/variables'; +import {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import BlockingView from './BlockingView'; -const propTypes = { +type FullPageNotFoundViewProps = { /** Child elements */ - children: PropTypes.node, + children?: React.ReactNode; /** If true, child components are replaced with a blocking "not found" view */ - shouldShow: PropTypes.bool, + shouldShow?: boolean; /** The key in the translations file to use for the title */ - titleKey: PropTypes.string, + titleKey?: TranslationPaths; /** The key in the translations file to use for the subtitle */ - subtitleKey: PropTypes.string, + subtitleKey?: TranslationPaths; /** Whether we should show a link to navigate elsewhere */ - shouldShowLink: PropTypes.bool, + shouldShowLink?: boolean; /** Whether we should show the back button on the header */ - shouldShowBackButton: PropTypes.bool, + shouldShowBackButton?: boolean; /** The key in the translations file to use for the go back link */ - linkKey: PropTypes.string, + linkKey?: TranslationPaths; /** Method to trigger when pressing the back button of the header */ - onBackButtonPress: PropTypes.func, + onBackButtonPress: () => void; /** Function to call when pressing the navigation link */ - onLinkPress: PropTypes.func, -}; - -const defaultProps = { - children: null, - shouldShow: false, - titleKey: 'notFound.notHere', - subtitleKey: 'notFound.pageNotFound', - linkKey: 'notFound.goBackHome', - onBackButtonPress: () => Navigation.goBack(ROUTES.HOME), - shouldShowLink: true, - shouldShowBackButton: true, - onLinkPress: () => Navigation.dismissModal(), + onLinkPress: () => void; }; // eslint-disable-next-line rulesdir/no-negated-variables -function FullPageNotFoundView({children, shouldShow, titleKey, subtitleKey, linkKey, onBackButtonPress, shouldShowLink, shouldShowBackButton, onLinkPress}) { +function FullPageNotFoundView({ + children = null, + shouldShow = false, + titleKey = 'notFound.notHere', + subtitleKey = 'notFound.pageNotFound', + linkKey = 'notFound.goBackHome', + onBackButtonPress = () => Navigation.goBack(ROUTES.HOME), + shouldShowLink = true, + shouldShowBackButton = true, + onLinkPress = () => Navigation.dismissModal(), +}: FullPageNotFoundViewProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + if (shouldShow) { return ( <> @@ -81,8 +80,6 @@ function FullPageNotFoundView({children, shouldShow, titleKey, subtitleKey, link return children; } -FullPageNotFoundView.propTypes = propTypes; -FullPageNotFoundView.defaultProps = defaultProps; FullPageNotFoundView.displayName = 'FullPageNotFoundView'; export default FullPageNotFoundView; diff --git a/src/components/BlockingViews/FullPageOfflineBlockingView.js b/src/components/BlockingViews/FullPageOfflineBlockingView.js deleted file mode 100644 index adbda21456dc..000000000000 --- a/src/components/BlockingViews/FullPageOfflineBlockingView.js +++ /dev/null @@ -1,42 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import * as Expensicons from '@components/Icon/Expensicons'; -import networkPropTypes from '@components/networkPropTypes'; -import {withNetwork} from '@components/OnyxProvider'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import useTheme from '@hooks/useTheme'; -import compose from '@libs/compose'; -import BlockingView from './BlockingView'; - -const propTypes = { - /** Child elements */ - children: PropTypes.node.isRequired, - - /** Props to fetch translation features */ - ...withLocalizePropTypes, - - /** Props to detect online status */ - network: networkPropTypes.isRequired, -}; - -function FullPageOfflineBlockingView(props) { - const theme = useTheme(); - - if (props.network.isOffline) { - return ( - - ); - } - - return props.children; -} - -FullPageOfflineBlockingView.propTypes = propTypes; -FullPageOfflineBlockingView.displayName = 'FullPageOfflineBlockingView'; - -export default compose(withLocalize, withNetwork())(FullPageOfflineBlockingView); diff --git a/src/components/BlockingViews/FullPageOfflineBlockingView.tsx b/src/components/BlockingViews/FullPageOfflineBlockingView.tsx new file mode 100644 index 000000000000..a9ebcf969ae5 --- /dev/null +++ b/src/components/BlockingViews/FullPageOfflineBlockingView.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import * as Expensicons from '@components/Icon/Expensicons'; +import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; +import useTheme from '@hooks/useTheme'; +import ChildrenProps from '@src/types/utils/ChildrenProps'; +import BlockingView from './BlockingView'; + +function FullPageOfflineBlockingView({children}: ChildrenProps) { + const {translate} = useLocalize(); + const {isOffline} = useNetwork(); + + const theme = useTheme(); + + if (isOffline) { + return ( + + ); + } + + return children; +} + +FullPageOfflineBlockingView.displayName = 'FullPageOfflineBlockingView'; + +export default FullPageOfflineBlockingView; diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 715603ea362e..ac18b550501d 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,4 +1,4 @@ -import React, {ForwardedRef, forwardRef, KeyboardEvent as ReactKeyboardEvent} from 'react'; +import React, {type ForwardedRef, forwardRef, type MouseEventHandler, type KeyboardEvent as ReactKeyboardEvent} from 'react'; import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; @@ -29,7 +29,7 @@ type CheckboxProps = Partial & { containerStyle?: StyleProp; /** Callback that is called when mousedown is triggered. */ - onMouseDown?: () => void; + onMouseDown?: MouseEventHandler; /** The size of the checkbox container */ containerSize?: number; diff --git a/src/components/ConfirmContent.js b/src/components/ConfirmContent.js deleted file mode 100644 index 13685c7392bb..000000000000 --- a/src/components/ConfirmContent.js +++ /dev/null @@ -1,173 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {View} from 'react-native'; -import _ from 'underscore'; -import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import variables from '@styles/variables'; -import Button from './Button'; -import Header from './Header'; -import Icon from './Icon'; -import sourcePropTypes from './Image/sourcePropTypes'; -import Text from './Text'; - -const propTypes = { - /** Title of the modal */ - title: PropTypes.string.isRequired, - - /** A callback to call when the form has been submitted */ - onConfirm: PropTypes.func.isRequired, - - /** A callback to call when the form has been closed */ - onCancel: PropTypes.func, - - /** Confirm button text */ - confirmText: PropTypes.string, - - /** Cancel button text */ - cancelText: PropTypes.string, - - /** Modal content text/element */ - prompt: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), - - /** Whether we should use the success button color */ - success: PropTypes.bool, - - /** Whether we should use the danger button color. Use if the action is destructive */ - danger: PropTypes.bool, - - /** Whether we should disable the confirm button when offline */ - shouldDisableConfirmButtonWhenOffline: PropTypes.bool, - - /** Whether we should show the cancel button */ - shouldShowCancelButton: PropTypes.bool, - - /** Icon to display above the title */ - iconSource: PropTypes.oneOfType([PropTypes.string, sourcePropTypes]), - - /** Whether to center the icon / text content */ - shouldCenterContent: PropTypes.bool, - - /** Whether to stack the buttons */ - shouldStackButtons: PropTypes.bool, - - /** Styles for title */ - // eslint-disable-next-line react/forbid-prop-types - titleStyles: PropTypes.arrayOf(PropTypes.object), - - /** Styles for prompt */ - // eslint-disable-next-line react/forbid-prop-types - promptStyles: PropTypes.arrayOf(PropTypes.object), - - /** Styles for view */ - // eslint-disable-next-line react/forbid-prop-types - contentStyles: PropTypes.arrayOf(PropTypes.object), - - /** Styles for icon */ - // eslint-disable-next-line react/forbid-prop-types - iconAdditionalStyles: PropTypes.arrayOf(PropTypes.object), -}; - -const defaultProps = { - confirmText: '', - cancelText: '', - prompt: '', - success: true, - danger: false, - onCancel: () => {}, - shouldDisableConfirmButtonWhenOffline: false, - shouldShowCancelButton: true, - contentStyles: [], - iconSource: null, - shouldCenterContent: false, - shouldStackButtons: true, - titleStyles: [], - promptStyles: [], - iconAdditionalStyles: [], -}; - -function ConfirmContent(props) { - const styles = useThemeStyles(); - const theme = useTheme(); - const {translate} = useLocalize(); - const {isOffline} = useNetwork(); - - const isCentered = props.shouldCenterContent; - - return ( - - - {!_.isEmpty(props.iconSource) || - (_.isFunction(props.iconSource) && ( - - - - ))} - - -
- - - {_.isString(props.prompt) ? {props.prompt} : props.prompt} - - - {props.shouldStackButtons ? ( - <> -