diff --git a/.eslintrc.js b/.eslintrc.js index 22b94d79e369..ac4546567833 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -164,7 +164,7 @@ module.exports = { }, }, { - files: ['tests/**/*.{js,jsx,ts,tsx}', '.github/**/*.{js,jsx,ts,tsx}'], + files: ['workflow_tests/**/*.{js,jsx,ts,tsx}', 'tests/**/*.{js,jsx,ts,tsx}', '.github/**/*.{js,jsx,ts,tsx}'], rules: { '@lwc/lwc/no-async-await': 'off', 'no-await-in-loop': 'off', diff --git a/.github/scripts/verifyPodfile.sh b/.github/scripts/verifyPodfile.sh index 3a57a736cd70..ec2709a25786 100755 --- a/.github/scripts/verifyPodfile.sh +++ b/.github/scripts/verifyPodfile.sh @@ -13,10 +13,10 @@ 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 - success "Automatic signing not enabled" + success "Automatic signing not enabled" else - error "Error: Automatic provisioning style is not allowed!" - EXIT_CODE=1 + error "Error: Automatic provisioning style is not allowed!" + EXIT_CODE=1 fi PODFILE_SHA=$(openssl sha1 ios/Podfile | awk '{print $2}') @@ -26,10 +26,26 @@ echo "Podfile: $PODFILE_SHA" echo "Podfile.lock: $PODFILE_LOCK_SHA" if [[ "$PODFILE_SHA" == "$PODFILE_LOCK_SHA" ]]; then - success "Podfile checksum verified!" + success "Podfile checksum verified!" else - error "Podfile.lock checksum mismatch. Did you forget to run \`npx pod-install\`?" - EXIT_CODE=1 + error "Podfile.lock checksum mismatch. Did you forget to run \`npx pod-install\`?" + EXIT_CODE=1 +fi + +info "Ensuring correct version of cocoapods is used..." + +POD_VERSION_REGEX='([[:digit:]]+\.[[:digit:]]+)(\.[[:digit:]]+)?'; +POD_VERSION_FROM_GEMFILE="$(sed -nr "s/gem \"cocoapods\", \"~> $POD_VERSION_REGEX\"/\1/p" Gemfile)" +info "Pod version from Gemfile: $POD_VERSION_FROM_GEMFILE" + +POD_VERSION_FROM_PODFILE_LOCK="$(sed -nr "s/COCOAPODS: $POD_VERSION_REGEX/\1/p" ios/Podfile.lock)" +info "Pod version from Podfile.lock: $POD_VERSION_FROM_PODFILE_LOCK" + +if [[ "$POD_VERSION_FROM_GEMFILE" == "$POD_VERSION_FROM_PODFILE_LOCK" ]]; then + success "Cocoapods version from Podfile.lock matches cocoapods version from Gemfile" +else + error "Cocoapods version from Podfile.lock does not match cocoapods version from Gemfile. Please use \`npm run pod-install\` or \`bundle exec pod install\` instead of \`pod install\` to install pods." + EXIT_CODE=1 fi info "Comparing Podfile.lock with node packages..." diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml index 494326869cca..b6558b049647 100644 --- a/.github/workflows/cherryPick.yml +++ b/.github/workflows/cherryPick.yml @@ -13,7 +13,8 @@ jobs: outputs: IS_DEPLOYER: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' }} steps: - - id: isDeployer + - name: Check if user is deployer + id: isDeployer run: | if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT" @@ -39,7 +40,8 @@ jobs: ref: staging token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Set up git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 8943669c2ba8..54ae1048b57b 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -13,18 +13,20 @@ jobs: # It does not run for pull requests created by OSBotify if: ${{ github.event.issue.pull_request || (github.event_name == 'pull_request_target' && github.event.pull_request.user.login != 'OSBotify') }} steps: - - uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 + - name: CLA comment check + uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 id: sign with: text: ${{ github.event.comment.body }} regex: '\s*I have read the CLA Document and I hereby sign the CLA\s*' - - uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 + - name: CLA comment re-check + uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 id: recheck with: text: ${{ github.event.comment.body }} regex: '\s*recheck\s*' - name: CLA Assistant - if: ${{ steps.recheck.outputs.match != '' || steps.sign.outputs.match != '' }} || github.event_name == 'pull_request_target' + if: ${{ steps.recheck.outputs.match != '' || steps.sign.outputs.match != '' || github.event_name == 'pull_request_target' }} # Version: 2.1.2-beta uses: cla-assistant/github-action@948230deb0d44dd38957592f08c6bd934d96d0cf env: diff --git a/.github/workflows/createNewVersion.yml b/.github/workflows/createNewVersion.yml index b2703731df79..ba907334c595 100644 --- a/.github/workflows/createNewVersion.yml +++ b/.github/workflows/createNewVersion.yml @@ -54,18 +54,21 @@ jobs: NEW_VERSION: ${{ steps.bumpVersion.outputs.NEW_VERSION }} steps: - - uses: softprops/turnstyle@ca99add00ff0c9cbc697d22631d2992f377e5bd5 + - name: Run turnstyle + uses: softprops/turnstyle@ca99add00ff0c9cbc697d22631d2992f377e5bd5 with: poll-interval-seconds: 10 env: GITHUB_TOKEN: ${{ github.token }} - - uses: actions/checkout@v3 + - name: Check out + uses: actions/checkout@v3 with: ref: main token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} @@ -89,7 +92,8 @@ jobs: - name: Update main branch run: git push origin main - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b3105ee05c2c..f2ff67680940 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,7 +15,8 @@ jobs: ref: staging token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} @@ -29,12 +30,14 @@ jobs: runs-on: ubuntu-latest if: github.ref == 'refs/heads/production' steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: production token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} diff --git a/.github/workflows/deployBlocker.yml b/.github/workflows/deployBlocker.yml index 8065a5c88cb2..f42d19ca8241 100644 --- a/.github/workflows/deployBlocker.yml +++ b/.github/workflows/deployBlocker.yml @@ -11,7 +11,8 @@ jobs: if: ${{ github.event.label.name == 'DeployBlockerCash' }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -63,7 +64,8 @@ jobs: 2. Find someone who can quickly fix the issue. 3. Fix the issue yourself. - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/finishReleaseCycle.yml b/.github/workflows/finishReleaseCycle.yml index 7b71f6263c88..e2323af2486e 100644 --- a/.github/workflows/finishReleaseCycle.yml +++ b/.github/workflows/finishReleaseCycle.yml @@ -23,7 +23,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - - name: Reopen and comment on issue + - name: Reopen and comment on issue (not a team member) if: ${{ !fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) }} uses: Expensify/App/.github/actions/javascript/reopenIssueWithComment@main with: @@ -41,8 +41,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} - - name: Reopen and comment on issue - if: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) && fromJSON(steps.checkDeployBlockers.outputs.HAS_DEPLOY_BLOCKERS) }} + - name: Reopen and comment on issue (has blockers) + if: ${{ fromJSON(steps.isDeployer.outputs.IS_DEPLOYER) && fromJSON(steps.checkDeployBlockers.outputs.HAS_DEPLOY_BLOCKERS || 'false') }} uses: Expensify/App/.github/actions/javascript/reopenIssueWithComment@main with: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} @@ -51,7 +51,8 @@ jobs: This issue either has unchecked items or has not yet been marked with the `:shipit:` emoji of approval. Reopening! - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} @@ -62,12 +63,14 @@ jobs: needs: validate if: ${{ fromJSON(needs.validate.outputs.isValid) }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: staging token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup Git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} @@ -79,7 +82,8 @@ jobs: # Force-update the remote production branch. git push --force origin production - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} @@ -98,12 +102,14 @@ jobs: runs-on: ubuntu-latest needs: [updateProduction, createNewPatchVersion] steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: main token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup Git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} @@ -115,7 +121,8 @@ jobs: # Force-update the remote staging branch git push --force origin staging - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1983e406c77b..5953a4aa89e2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,9 +11,11 @@ jobs: if: ${{ github.actor != 'OSBotify' || github.event_name == 'workflow_call' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Lint JavaScript and Typescript with ESLint run: npm run lint diff --git a/.github/workflows/lockDeploys.yml b/.github/workflows/lockDeploys.yml index a49a5519f690..6ca025bb2a25 100644 --- a/.github/workflows/lockDeploys.yml +++ b/.github/workflows/lockDeploys.yml @@ -9,7 +9,8 @@ jobs: if: ${{ github.event.label.name == '🔐 LockCashDeploys 🔐' && contains(github.event.issue.labels.*.name, 'StagingDeployCash') && github.actor != 'OSBotify' }} runs-on: macos-12 steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: main token: ${{ secrets.OS_BOTIFY_TOKEN }} @@ -27,7 +28,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} - - if: ${{ failure() }} + - name: Announce failed workflow + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml index 400a0d4364fe..ad002e164837 100644 --- a/.github/workflows/platformDeploy.yml +++ b/.github/workflows/platformDeploy.yml @@ -18,7 +18,8 @@ jobs: outputs: IS_DEPLOYER: ${{ fromJSON(steps.isUserDeployer.outputs.IS_DEPLOYER) || github.actor == 'OSBotify' }} steps: - - id: isUserDeployer + - name: Check if user is deployer + id: isUserDeployer run: | if gh api /orgs/Expensify/teams/mobile-deployers/memberships/${{ github.actor }} --silent; then echo "IS_DEPLOYER=true" >> "$GITHUB_OUTPUT" @@ -32,14 +33,17 @@ jobs: deployChecklist: name: Create or update deploy checklist runs-on: ubuntu-latest + if: ${{ github.event_name != 'release' }} needs: validateActor steps: - - uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Set version id: getVersion - run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" + run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_OUTPUT" - name: Create or update staging deploy uses: Expensify/App/.github/actions/javascript/createOrUpdateStagingDeploy@main @@ -53,14 +57,17 @@ jobs: if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} runs-on: ubuntu-latest-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - name: Configure MapBox SDK run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 + - name: Setup Ruby + uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 with: ruby-version: '2.7' bundler-cache: true @@ -127,9 +134,11 @@ jobs: if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} runs-on: macos-12-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Decrypt Developer ID Certificate run: cd desktop && gpg --quiet --batch --yes --decrypt --passphrase="$DEVELOPER_ID_SECRET_PASSPHRASE" --output developer_id.p12 developer_id.p12.gpg @@ -164,20 +173,36 @@ jobs: if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} runs-on: macos-12-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - name: Configure MapBox SDK run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 + - name: Setup Ruby + uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 with: ruby-version: '2.7' bundler-cache: true + - name: Cache Pod dependencies + uses: actions/cache@v3 + id: pods-cache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-cache-${{ hashFiles('ios/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods-cache- + + - name: Compare Podfile.lock and Manifest.lock + id: compare-podfile-and-manifest + run: echo "IS_PODFILE_SAME_AS_MANIFEST=${{ hashFiles('ios/Podfile.lock') == hashFiles('ios/Pods/Manifest.lock') }}" >> "$GITHUB_OUTPUT" + - name: Install cocoapods uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350 + if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true' with: timeout_minutes: 10 max_attempts: 5 @@ -253,9 +278,11 @@ jobs: if: ${{ fromJSON(needs.validateActor.outputs.IS_DEPLOYER) }} runs-on: ubuntu-latest-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Setup Cloudflare CLI run: pip3 install cloudflare @@ -310,7 +337,8 @@ jobs: if: ${{ failure() }} needs: [android, desktop, iOS, web] steps: - - uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main + - name: Post Slack message on failure + uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} @@ -320,7 +348,8 @@ jobs: if: ${{ success() }} needs: [android, desktop, iOS, web] steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - name: Set version run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" @@ -380,9 +409,11 @@ jobs: if: ${{ always() }} needs: [android, desktop, iOS, web] steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Set version run: echo "VERSION=$(npm run print-version --silent)" >> "$GITHUB_ENV" diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index e3977734fc50..186490c7baaf 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -2,7 +2,8 @@ name: Process new code merged to main on: push: - branches: [main] + branches: + - main jobs: typecheck: @@ -20,12 +21,14 @@ jobs: if: ${{ always() }} steps: - - if: ${{ needs.typecheck.result == 'failure' || needs.lint.result == 'failure' || needs.test.result == 'failure' }} + - name: Announce failed workflow in Slack + if: ${{ needs.typecheck.result == 'failure' || needs.lint.result == 'failure' || needs.test.result == 'failure' }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} - - if: ${{ needs.typecheck.result == 'failure' || needs.lint.result == 'failure' || needs.test.result == 'failure' }} + - name: Exit failed workflow + if: ${{ needs.typecheck.result == 'failure' || needs.lint.result == 'failure' || needs.test.result == 'failure' }} run: exit 1 chooseDeployActions: @@ -33,7 +36,7 @@ jobs: needs: confirmPassingBuild outputs: MERGED_PR: ${{ steps.getMergedPullRequest.outputs.number }} - SHOULD_DEPLOY: ${{ steps.shouldDeploy.outputs.SHOULD_DEPLOY }} + SHOULD_DEPLOY: ${{ fromJSON(steps.shouldDeploy.outputs.SHOULD_DEPLOY) }} steps: - name: Get merged pull request @@ -75,18 +78,21 @@ jobs: needs: [chooseDeployActions, createNewVersion] runs-on: ubuntu-latest steps: - - uses: softprops/turnstyle@ca99add00ff0c9cbc697d22631d2992f377e5bd5 + - name: Run turnstyle + uses: softprops/turnstyle@ca99add00ff0c9cbc697d22631d2992f377e5bd5 with: poll-interval-seconds: 10 env: GITHUB_TOKEN: ${{ github.token }} - - uses: actions/checkout@v3 + - name: Checkout main + uses: actions/checkout@v3 with: ref: main token: ${{ secrets.OS_BOTIFY_TOKEN }} - - uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main + - name: Setup Git for OSBotify + uses: Expensify/App/.github/actions/composite/setupGitForOSBotify@main with: GPG_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} @@ -98,7 +104,8 @@ jobs: # Force-update the remote staging branch git push --force origin staging - - if: ${{ failure() }} + - name: Announce failed workflow in Slack + if: ${{ failure() }} uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main with: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} @@ -134,7 +141,8 @@ jobs: if: ${{ github.actor != 'OSBotify' && !fromJSON(needs.isExpensifyEmployee.outputs.IS_EXPENSIFY_EMPLOYEE) }} steps: # Version: 2.3.4 - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 with: token: ${{ secrets.OS_BOTIFY_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e79a02281ae0..72bdd0468fd2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,9 +18,11 @@ jobs: chunk: [ 1, 2, 3 ] name: test (job ${{ fromJSON(matrix.chunk) }}) steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Get number of CPU cores id: cpu-cores @@ -53,9 +55,11 @@ jobs: runs-on: ubuntu-latest name: Shell tests steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Test CI git logic run: tests/unit/CIGitLogicTest.sh diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 16fffcc2c65e..755ab6dbaa60 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -19,7 +19,8 @@ jobs: outputs: READY_TO_BUILD: ${{ fromJSON(steps.isExpensifyEmployee.outputs.IS_EXPENSIFY_EMPLOYEE) && fromJSON(steps.hasReadyToBuildLabel.outputs.HAS_READY_TO_BUILD_LABEL) }} steps: - - id: isExpensifyEmployee + - name: Is Expensify employee + id: isExpensifyEmployee run: | if gh api /orgs/Expensify/teams/expensify-expensify/memberships/${{ github.actor }} --silent; then echo "IS_EXPENSIFY_EMPLOYEE=true" >> "$GITHUB_OUTPUT" @@ -70,7 +71,8 @@ jobs: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} steps: # This action checks-out the repository, so the workflow can access it. - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 with: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} @@ -80,9 +82,11 @@ jobs: sed -i 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 + - name: Setup Ruby + uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 with: ruby-version: '2.7' bundler-cache: true @@ -117,7 +121,8 @@ jobs: MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }} MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} - - uses: actions/upload-artifact@v3 + - name: Upload Artifact + uses: actions/upload-artifact@v3 with: name: android path: ./android_paths.json @@ -131,7 +136,8 @@ jobs: runs-on: macos-12-xl steps: # This action checks-out the repository, so the workflow can access it. - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - name: Checkout + uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 with: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} @@ -144,18 +150,33 @@ jobs: sed -i '' 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - - name: Setup Xcode + - name: Setup XCode run: sudo xcode-select -switch /Applications/Xcode_14.2.app - - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 + - name: Setup Ruby + uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 with: ruby-version: '2.7' bundler-cache: true + - name: Cache Pod dependencies + uses: actions/cache@v3 + id: pods-cache + with: + path: ios/Pods + key: ${{ runner.os }}-pods-cache-${{ hashFiles('ios/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods-cache- + + - name: Compare Podfile.lock and Manifest.lock + id: compare-podfile-and-manifest + run: echo "IS_PODFILE_SAME_AS_MANIFEST=${{ hashFiles('ios/Podfile.lock') == hashFiles('ios/Pods/Manifest.lock') }}" >> "$GITHUB_OUTPUT" + - name: Install cocoapods uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350 + if: steps.pods-cache.outputs.cache-hit != 'true' || steps.compare-podfile-and-manifest.outputs.IS_PODFILE_SAME_AS_MANIFEST != 'true' with: timeout_minutes: 10 max_attempts: 5 @@ -185,7 +206,8 @@ jobs: S3_BUCKET: ad-hoc-expensify-cash S3_REGION: us-east-1 - - uses: actions/upload-artifact@v3 + - name: Upload Artifact + uses: actions/upload-artifact@v3 with: name: ios path: ./ios_paths.json @@ -198,7 +220,8 @@ jobs: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} @@ -208,7 +231,8 @@ jobs: sed -i '' 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Decrypt Developer ID Certificate run: cd desktop && gpg --quiet --batch --yes --decrypt --passphrase="$DEVELOPER_ID_SECRET_PASSPHRASE" --output developer_id.p12 developer_id.p12.gpg @@ -239,7 +263,8 @@ jobs: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: ubuntu-latest-xl steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} @@ -249,7 +274,8 @@ jobs: sed -i 's/ENVIRONMENT=staging/ENVIRONMENT=adhoc/' .env.adhoc echo "PULL_REQUEST_NUMBER=$PULL_REQUEST_NUMBER" >> .env.adhoc - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main - name: Configure AWS Credentials uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main @@ -270,7 +296,7 @@ jobs: postGithubComment: runs-on: ubuntu-latest name: Post a GitHub comment with app download links for testing - needs: [validateActor, getBranchRef, android, ios, desktop, web] + needs: [validateActor, getBranchRef, android, iOS, desktop, web] if: ${{ always() }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} @@ -281,7 +307,8 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} - - uses: actions/download-artifact@v3 + - name: Download Artifact + uses: actions/download-artifact@v3 if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }} - name: Read JSONs with android paths @@ -297,7 +324,7 @@ jobs: - name: Read JSONs with iOS paths id: get_ios_path - if: ${{ needs.ios.result == 'success' }} + if: ${{ needs.iOS.result == 'success' }} run: | content_ios="$(cat ./ios/ios_paths.json)" content_ios="${content_ios//'%'/'%25'}" @@ -327,6 +354,6 @@ jobs: IOS: ${{ needs.iOS.result }} WEB: ${{ needs.web.result }} ANDROID_LINK: ${{steps.get_android_path.outputs.android_path}} - DESKTOP_LINK: https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/${{ env.PULL_REQUEST_NUMBER }}/NewExpensify.dmg + DESKTOP_LINK: https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/${{ env.PULL_REQUEST_NUMBER }}/NewExpensifyAdHoc.dmg IOS_LINK: ${{steps.get_ios_path.outputs.ios_path}} WEB_LINK: https://${{ env.PULL_REQUEST_NUMBER }}.pr-testing.expensify.com diff --git a/.github/workflows/validateGithubActions.yml b/.github/workflows/validateGithubActions.yml index f496c5e4b27e..bcda941e1b05 100644 --- a/.github/workflows/validateGithubActions.yml +++ b/.github/workflows/validateGithubActions.yml @@ -12,9 +12,11 @@ jobs: if: github.actor != 'OSBotify' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - - uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main # Rebuild all the actions on this branch and check for a diff. Fail if there is one, # because that would be a sign that the PR author did not rebuild the Github Actions diff --git a/.github/workflows/verifyPodfile.yml b/.github/workflows/verifyPodfile.yml index 64188769f0bd..d8d931e476d1 100644 --- a/.github/workflows/verifyPodfile.yml +++ b/.github/workflows/verifyPodfile.yml @@ -14,8 +14,9 @@ jobs: if: github.actor != 'OSBotify' runs-on: macos-latest steps: - - uses: actions/checkout@v3 - - - uses: Expensify/App/.github/actions/composite/setupNode@main - - - run: ./.github/scripts/verifyPodfile.sh + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Node + uses: Expensify/App/.github/actions/composite/setupNode@main + - name: Verify podfile + run: ./.github/scripts/verifyPodfile.sh diff --git a/.github/workflows/verifySignedCommits.yml b/.github/workflows/verifySignedCommits.yml index e1068e71e041..ee1b0c4c78da 100644 --- a/.github/workflows/verifySignedCommits.yml +++ b/.github/workflows/verifySignedCommits.yml @@ -9,6 +9,7 @@ jobs: verifySignedCommits: runs-on: ubuntu-latest steps: - - uses: Expensify/App/.github/actions/javascript/verifySignedCommits@main + - name: Verify signed commits + uses: Expensify/App/.github/actions/javascript/verifySignedCommits@main with: GITHUB_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 4919ddc1fdc9..aae9baad529f 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,9 @@ tests/e2e/results/ # Typescript tsconfig.tsbuildinfo + +# Mock-github +/repo/ + +# Workflow test logs +/workflow_tests/logs/ diff --git a/.well-known/apple-app-site-association b/.well-known/apple-app-site-association index 9274dd8c1382..c871764117ed 100644 --- a/.well-known/apple-app-site-association +++ b/.well-known/apple-app-site-association @@ -63,6 +63,14 @@ { "/": "/new/*", "comment": "New Chat" + }, + { + "/": "/workspace/*", + "comment": "Workspace Details" + }, + { + "/": "/teachersunite/*", + "comment": "Teachers Unite!" } ] } diff --git a/android/app/build.gradle b/android/app/build.gradle index bd38d9ebe4ba..1867a8cf85d2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,7 +22,7 @@ react { // The list of variants to that are debuggable. For those we're going to // skip the bundling of the JS bundle and the assets. By default is just 'debug'. // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. - debuggableVariants = ["developmentDebug"] + debuggableVariants = ["developmentDebug", "productionDebug"] /* Bundling */ // A list containing the node command and its flags. Default is just 'node'. @@ -90,8 +90,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001036702 - versionName "1.3.67-2" + versionCode 1001037002 + versionName "1.3.70-2" } flavorDimensions "default" diff --git a/android/app/src/main/res/drawable-hdpi/ic_notification.png b/android/app/src/main/res/drawable-hdpi/ic_notification.png index 5a36b56c4bc9..7612112d1bc5 100644 Binary files a/android/app/src/main/res/drawable-hdpi/ic_notification.png and b/android/app/src/main/res/drawable-hdpi/ic_notification.png differ diff --git a/android/app/src/main/res/drawable-mdpi/ic_notification.png b/android/app/src/main/res/drawable-mdpi/ic_notification.png index 502b45ac86bd..89accf5424f8 100644 Binary files a/android/app/src/main/res/drawable-mdpi/ic_notification.png and b/android/app/src/main/res/drawable-mdpi/ic_notification.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/ic_notification.png b/android/app/src/main/res/drawable-xhdpi/ic_notification.png index d03ded01cf16..a01f2c5e0dc9 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/ic_notification.png and b/android/app/src/main/res/drawable-xhdpi/ic_notification.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_notification.png b/android/app/src/main/res/drawable-xxhdpi/ic_notification.png index cb9b4b24e518..3bb969329c79 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/ic_notification.png and b/android/app/src/main/res/drawable-xxhdpi/ic_notification.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png b/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png index 2469d9193901..697922b1e689 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png and b/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png differ diff --git a/assets/animations/Safe.json b/assets/animations/Safe.json new file mode 100644 index 000000000000..15d4f4917dd0 --- /dev/null +++ b/assets/animations/Safe.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":24,"ip":0,"op":64,"w":625,"h":400,"nm":"C","assets":[{"id":"comp_0","nm":"E","fr":24,"layers":[{"ind":1,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.1},"t":38,"s":[1002.5,667.5,0],"to":[25.25,-33.75,0],"ti":[-25.25,33.75,0]},{"t":48,"s":[1154,465,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"t":48,"s":[25,25,100]}],"l":2}},"ao":0,"ip":38,"op":49,"st":0},{"ind":2,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":38,"s":[941.5,674.5,0],"to":[-30.25,-30,0],"ti":[30.25,30,0]},{"t":48,"s":[760,494.5,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"t":48,"s":[25,25,100]}],"l":2}},"ao":0,"ip":38,"op":49,"st":0},{"ind":3,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.041},"t":38,"s":[984,730.5,0],"to":[7.333,29.25,0],"ti":[-7.333,-29.25,0]},{"t":48,"s":[1028,906,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"t":48,"s":[25,25,100]}],"l":2}},"ao":0,"ip":38,"op":49,"st":0},{"ind":4,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.166},"t":39,"s":[995.5,714.5,0],"to":[42,3.333,0],"ti":[-42,-3.333,0]},{"t":49,"s":[1247.5,734.5,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":39,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":44,"s":[100,100,100]},{"t":49,"s":[25,25,100]}],"l":2}},"ao":0,"ip":39,"op":50,"st":0},{"ind":5,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.036},"t":39,"s":[957.5,666.5,0],"to":[9.167,-41.5,0],"ti":[-9.167,41.5,0]},{"t":49,"s":[1012.5,417.5,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":39,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":44,"s":[100,100,100]},{"t":49,"s":[25,25,100]}],"l":2}},"ao":0,"ip":39,"op":50,"st":0},{"ind":6,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":39,"s":[932,732.5,0],"to":[-20.75,21.5,0],"ti":[20.75,-21.5,0]},{"t":49,"s":[807.5,861.5,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":39,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":44,"s":[100,100,100]},{"t":49,"s":[25,25,100]}],"l":2}},"ao":0,"ip":39,"op":50,"st":0},{"ind":7,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":41,"s":[-44]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":46,"s":[0]},{"t":51,"s":[48]}]},"p":{"a":0,"k":[1033,663,0],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":41,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":46,"s":[100,100,100]},{"t":51,"s":[25,25,100]}],"l":2}},"ao":0,"ip":41,"op":52,"st":0},{"ind":8,"ty":3,"nm":"s","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":45,"s":[-45]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":49,"s":[0]},{"t":54,"s":[48]}]},"p":{"a":0,"k":[906,769,0],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":45,"s":[25,25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":49,"s":[100,100,100]},{"t":54,"s":[25,25,100]}],"l":2}},"ao":0,"ip":44,"op":55,"st":2},{"ind":9,"ty":3,"nm":"b","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":0,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":5,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":33,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":37,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":38,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":42,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":52,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.65,"y":0.65},"o":{"x":0.313,"y":0.313},"t":57,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.378,"y":0.378},"t":59,"s":[886,870,0],"to":[0,0,0],"ti":[0,0,0]},{"t":63,"s":[886,870,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[106,92,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[0.407,0.407,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0.273,0.273,0]},"t":37,"s":[98.704,102.592,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[98,104,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":42,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":52,"s":[100,100,100]},{"i":{"x":[0.65,0.65,0.65],"y":[-0.264,-0.264,1]},"o":{"x":[0.313,0.313,0.313],"y":[0,0,0]},"t":57,"s":[97,103,100]},{"i":{"x":[0.831,0.831,0.831],"y":[0.881,0.881,1]},"o":{"x":[0.378,0.378,0.378],"y":[0.16,0.16,0]},"t":59,"s":[97.166,102.834,100]},{"t":63,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":10,"ty":3,"nm":"h","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[93,-80,0],"to":[0.667,0,0],"ti":[-0.667,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[97,-80,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":33,"s":[97,-80,0],"to":[13.333,0,0],"ti":[-13.333,0,0]},{"t":37,"s":[177,-80,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":11,"ty":3,"nm":"h","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9,"s":[0]},{"i":{"x":[0.694],"y":[0.113]},"o":{"x":[0.299],"y":[0]},"t":14,"s":[13]},{"i":{"x":[0.79],"y":[0.911]},"o":{"x":[0.43],"y":[0.241]},"t":19,"s":[-6.26]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":21,"s":[-46]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[-81]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":23,"s":[-125]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[-241]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[-285]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":26,"s":[-319]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":32,"s":[-376]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":33,"s":[-376]},{"t":37,"s":[-372]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[90,-80,0],"to":[0.833,0,0],"ti":[-0.833,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[95,-80,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":33,"s":[95,-80,0],"to":[13.333,0,0],"ti":[-13.333,0,0]},{"t":37,"s":[175,-80,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[55,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":12,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[182,-134,0],"to":[0.667,0,0],"ti":[-0.667,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[186,-134,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":33,"s":[186,-134,0],"to":[6.5,0,0],"ti":[-6.5,0,0]},{"t":37,"s":[225,-134,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[80,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":13,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[170,-139,0],"to":[0.667,0,0],"ti":[-0.667,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[174,-139,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":33,"s":[174,-139,0],"to":[5.833,0,0],"ti":[-5.833,0,0]},{"t":37,"s":[209,-139,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[53,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":14,"ty":3,"nm":"b","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[49,52,0],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":15,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":0,"s":[223,-145,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[223,-145,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":33,"s":[223,-145,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[223,-145,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[114,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[42,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":16,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[75.5,-107.5,0],"to":[0.583,0.583,0],"ti":[-0.583,-0.583,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":6,"s":[79,-104,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":33,"s":[79,-104,0],"to":[14.333,0,0],"ti":[-14.333,0,0]},{"t":37,"s":[165,-104,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":33,"s":[100,100,100]},{"t":37,"s":[100,100,100]}],"l":2}},"ao":0,"ip":0,"op":38,"st":0},{"ind":17,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":38,"s":[222,-147,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":43,"s":[222,-147,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":51,"s":[222,-147,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.65,"y":0.65},"o":{"x":0.313,"y":0.313},"t":57,"s":[222,-147,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.378,"y":0.378},"t":59,"s":[222,-147,0],"to":[0,0,0],"ti":[0,0,0]},{"t":63,"s":[222,-147,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[111,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":51,"s":[100,100,100]},{"i":{"x":[0.65,0.65,0.65],"y":[-0.264,1,1]},"o":{"x":[0.313,0.313,0.313],"y":[0,0,0]},"t":57,"s":[111,100,100]},{"i":{"x":[0.831,0.831,0.831],"y":[0.881,1,1]},"o":{"x":[0.378,0.378,0.378],"y":[0.16,0,0]},"t":59,"s":[108.452,100,100]},{"t":63,"s":[65,100,100]}],"l":2}},"ao":0,"ip":38,"op":64,"st":0},{"ind":18,"ty":3,"nm":"d","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[306,-107,0],"to":[-1.333,0,0],"ti":[1.333,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":43,"s":[298,-107,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[298,-107,0],"to":[1.333,0,0],"ti":[4.333,0,0]},{"i":{"x":0.723,"y":1},"o":{"x":0.313,"y":0},"t":57,"s":[306,-107,0],"to":[-0.439,0,0],"ti":[0.802,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.378,"y":0},"t":59,"s":[304.119,-107,0],"to":[-7.123,0,0],"ti":[5.093,0,0]},{"t":63,"s":[272,-107,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[109,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":43,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":51,"s":[100,100,100]},{"i":{"x":[0.65,0.65,0.65],"y":[-0.264,1,1]},"o":{"x":[0.313,0.313,0.313],"y":[0,0,0]},"t":57,"s":[109,100,100]},{"i":{"x":[0.831,0.831,0.831],"y":[0.881,1,1]},"o":{"x":[0.378,0.378,0.378],"y":[0.16,0,0]},"t":59,"s":[106.563,100,100]},{"t":63,"s":[65,100,100]}],"l":2}},"ao":0,"ip":38,"op":64,"st":0},{"ind":19,"ty":3,"nm":"b","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[49,52,0],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":20,"ty":3,"nm":"c","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":34,"s":[914,792,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[914,782,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[914,795,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":48,"s":[914,792,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[914,792,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[914,788,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[914,792,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":21,"ty":3,"nm":"c","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":34,"s":[969,759,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[969,749,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[969,762,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":48,"s":[969,759,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[969,759,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[969,755,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[969,759,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":22,"ty":3,"nm":"c","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":34,"s":[1017,763,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[1017,753,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[1017,766,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":48,"s":[1017,763,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[1017,763,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[1017,759,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[1017,763,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":23,"ty":3,"nm":"g","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[1015,712,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[1015,702,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45,"s":[1015,715,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":50,"s":[1015,712,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":54,"s":[1015,712,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[1015,708,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[1015,712,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":24,"ty":3,"nm":"g","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[931,726,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[931,716,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45,"s":[931,729,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":50,"s":[931,726,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":54,"s":[931,726,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[931,722,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[931,726,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":25,"ty":3,"nm":"c","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[955,679,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":42,"s":[955,669,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":47,"s":[955,682,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":52,"s":[955,679,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[955,679,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[955,675,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[955,679,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":26,"ty":3,"nm":"c","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":38,"s":[1025,686,0],"to":[0,-1.667,0],"ti":[0,-0.5,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":42,"s":[1025,676,0],"to":[0,0.5,0],"ti":[0,-1.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":47,"s":[1025,689,0],"to":[0,1.667,0],"ti":[0,0.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":52,"s":[1025,686,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[1025,686,0],"to":[0,-0.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[1025,682,0],"to":[0,0,0],"ti":[0,-0.667,0]},{"t":63,"s":[1025,686,0]}],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":27,"ty":3,"nm":"b","parent":9,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":0,"k":[142,-112,0],"l":2},"a":{"a":0,"k":[49,52,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":28,"ty":4,"nm":"s","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-122,94,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.466,-2.97],[0,0],[-1.301,-0.189],[0,0],[2.372,-2.313],[0,0],[-0.223,-1.297],[0,0],[2.932,1.542],[0,0],[1.165,-0.612],[0,0],[-0.559,3.265],[0,0],[0.941,0.918],[0,0],[-3.278,0.476],[0,0],[-0.582,1.179],[0,0]],"o":[[0,0],[0.582,1.179],[0,0],[3.278,0.476],[0,0],[-0.942,0.918],[0,0],[0.56,3.265],[0,0],[-1.164,-0.612],[0,0],[-2.932,1.542],[0,0],[0.222,-1.297],[0,0],[-2.372,-2.313],[0,0],[1.302,-0.189],[0,0],[1.466,-2.97]],"v":[[3.584,-16.859],[6.572,-10.804],[9.581,-8.618],[16.263,-7.647],[18.478,-0.83],[13.643,3.882],[12.494,7.42],[13.635,14.074],[7.836,18.287],[1.859,15.145],[-1.86,15.145],[-7.836,18.287],[-13.635,14.074],[-12.493,7.42],[-13.642,3.882],[-18.477,-0.83],[-16.262,-7.647],[-9.581,-8.618],[-6.572,-10.804],[-3.584,-16.859]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1131.528,497.634]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.986,1.549],[0,0],[2.113,0],[0.423,-0.563],[0,0],[1.55,-0.282],[0,0],[0.282,-1.268],[-1.408,-1.268],[0,0],[0.705,-2.113],[0,0],[-1.691,-0.564],[-1.127,0.845],[0,0],[-0.563,-0.563],[0,0],[-0.704,0.845],[0.141,1.691],[0,0],[-1.127,1.127],[0,0],[1.127,1.408],[1.128,0.282]],"o":[[0,0],[-0.986,-1.55],[0,0],[-2.113,0],[-0.422,0.564],[0,0],[-1.549,0.282],[0,0],[-0.282,1.268],[1.409,1.268],[0,0],[-0.704,2.113],[0,0],[1.69,0.563],[1.127,-0.845],[0,0],[0.564,0.564],[0,0],[0.705,-0.845],[-0.141,-1.69],[0,0],[1.128,-1.127],[0,0],[-1.127,-1.409],[-1.126,-0.281]],"v":[[8.425,-8.645],[6.128,-11.128],[3.31,-17.187],[-0.212,-18.878],[-3.734,-16.623],[-7.256,-9.721],[-10.637,-8.312],[-16.835,-7.326],[-19.512,-4.789],[-18.667,-0.422],[-13.454,4.367],[-12.75,8.031],[-13.595,14.37],[-12.186,18.315],[-6.974,18.032],[-1.339,14.933],[2.042,15.638],[7.959,18.596],[12.185,17.891],[13.453,14.229],[12.326,7.185],[13.312,4.086],[19.229,-1.549],[18.948,-5.352],[15.566,-7.466]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1131.759,497.456]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":39,"op":49,"st":0},{"ind":29,"ty":4,"nm":"s","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[219,68,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.466,-2.97],[0,0],[-1.302,-0.189],[0,0],[2.372,-2.312],[0,0],[-0.222,-1.297],[0,0],[2.932,1.542],[0,0],[1.165,-0.612],[0,0],[-0.559,3.265],[0,0],[0.942,0.918],[0,0],[-3.278,0.476],[0,0],[-0.582,1.179],[0,0]],"o":[[0,0],[0.582,1.179],[0,0],[3.278,0.476],[0,0],[-0.942,0.918],[0,0],[0.56,3.265],[0,0],[-1.164,-0.612],[0,0],[-2.932,1.542],[0,0],[0.222,-1.297],[0,0],[-2.372,-2.312],[0,0],[1.302,-0.189],[0,0],[1.466,-2.97]],"v":[[3.584,-16.859],[6.572,-10.804],[9.581,-8.618],[16.263,-7.647],[18.478,-0.831],[13.643,3.882],[12.493,7.42],[13.635,14.074],[7.836,18.287],[1.859,15.145],[-1.86,15.145],[-7.836,18.287],[-13.635,14.074],[-12.493,7.42],[-13.643,3.882],[-18.477,-0.831],[-16.262,-7.647],[-9.581,-8.618],[-6.572,-10.804],[-3.584,-16.859]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[790.365,522.523]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.986,1.549],[0,0],[2.113,0],[0.423,-0.563],[0,0],[1.55,-0.282],[0,0],[0.282,-1.268],[-1.409,-1.268],[0,0],[0.704,-2.113],[0,0],[-1.691,-0.564],[-1.127,0.845],[0,0],[-0.563,-0.563],[0,0],[-0.704,0.845],[0.141,1.691],[0,0],[-1.127,1.127],[0,0],[1.127,1.409],[1.127,0.282]],"o":[[0,0],[-0.987,-1.55],[0,0],[-2.113,0],[-0.422,0.564],[0,0],[-1.549,0.282],[0,0],[-0.282,1.268],[1.409,1.268],[0,0],[-0.704,2.113],[0,0],[1.69,0.563],[1.127,-0.845],[0,0],[0.564,0.564],[0,0],[0.705,-0.845],[-0.141,-1.69],[0,0],[1.127,-1.127],[0,0],[-1.127,-1.408],[-1.127,-0.281]],"v":[[8.426,-8.645],[6.129,-11.128],[3.311,-17.187],[-0.211,-18.878],[-3.733,-16.623],[-7.255,-9.721],[-10.636,-8.312],[-16.834,-7.326],[-19.511,-4.789],[-18.666,-0.422],[-13.453,4.367],[-12.749,8.031],[-13.594,14.37],[-12.185,18.315],[-6.973,18.032],[-1.338,14.933],[2.043,15.638],[7.96,18.596],[12.186,17.891],[13.454,14.229],[12.327,7.185],[13.313,4.086],[19.23,-1.549],[18.948,-5.354],[15.567,-7.466]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[790.595,522.345]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":39,"op":49,"st":0},{"ind":30,"ty":4,"nm":"s","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-13,-288,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.466,-2.97],[0,0],[-1.301,-0.189],[0,0],[2.372,-2.312],[0,0],[-0.222,-1.297],[0,0],[2.932,1.542],[0,0],[1.165,-0.612],[0,0],[-0.56,3.265],[0,0],[0.942,0.918],[0,0],[-3.278,0.476],[0,0],[-0.582,1.179],[0,0]],"o":[[0,0],[0.582,1.179],[0,0],[3.278,0.476],[0,0],[-0.942,0.918],[0,0],[0.56,3.265],[0,0],[-1.164,-0.612],[0,0],[-2.932,1.542],[0,0],[0.222,-1.297],[0,0],[-2.372,-2.312],[0,0],[1.302,-0.189],[0,0],[1.466,-2.97]],"v":[[3.583,-16.859],[6.571,-10.804],[9.58,-8.618],[16.262,-7.647],[18.477,-0.831],[13.642,3.882],[12.492,7.42],[13.634,14.074],[7.835,18.287],[1.859,15.145],[-1.861,15.145],[-7.837,18.287],[-13.635,14.074],[-12.494,7.42],[-13.644,3.882],[-18.478,-0.831],[-16.263,-7.647],[-9.582,-8.618],[-6.573,-10.804],[-3.585,-16.859]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1021.652,878.862]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.986,1.549],[0,0],[2.113,0],[0.423,-0.563],[0,0],[1.55,-0.282],[0,0],[0.282,-1.268],[-1.408,-1.268],[0,0],[0.705,-2.113],[0,0],[-1.691,-0.564],[-1.127,0.845],[0,0],[-0.563,-0.563],[0,0],[-0.704,0.845],[0.141,1.691],[0,0],[-1.127,1.127],[0,0],[1.127,1.409],[1.128,0.282]],"o":[[0,0],[-0.986,-1.55],[0,0],[-2.113,0],[-0.422,0.564],[0,0],[-1.549,0.282],[0,0],[-0.282,1.268],[1.409,1.268],[0,0],[-0.704,2.113],[0,0],[1.69,0.563],[1.127,-0.845],[0,0],[0.564,0.564],[0,0],[0.705,-0.845],[-0.141,-1.69],[0,0],[1.128,-1.127],[0,0],[-1.127,-1.408],[-1.126,-0.281]],"v":[[8.425,-8.645],[6.128,-11.128],[3.31,-17.187],[-0.212,-18.878],[-3.734,-16.623],[-7.256,-9.721],[-10.637,-8.312],[-16.835,-7.326],[-19.512,-4.789],[-18.667,-0.423],[-13.454,4.367],[-12.75,8.03],[-13.595,14.37],[-12.186,18.315],[-6.974,18.032],[-1.339,14.933],[2.042,15.638],[7.959,18.596],[12.185,17.891],[13.453,14.228],[12.326,7.185],[13.312,4.086],[19.229,-1.549],[18.948,-5.354],[15.566,-7.466]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1021.883,878.685]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":39,"op":49,"st":0},{"ind":31,"ty":4,"nm":"s","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-198,-141,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.137,-2.531],[0,0],[-1.309,0.129],[0,0],[1.747,-2.815],[0,0],[-0.528,-1.205],[0,0],[3.216,0.791],[0,0],[0.983,-0.874],[0,0],[0.241,3.304],[0,0],[1.135,0.665],[0,0],[-3.068,1.25],[0,0],[-0.281,1.285],[0,0]],"o":[[0,0],[0.848,1.005],[0,0],[3.296,-0.326],[0,0],[-0.694,1.118],[0,0],[1.328,3.035],[0,0],[-1.277,-0.315],[0,0],[-2.476,2.201],[0,0],[-0.096,-1.311],[0,0],[-2.858,-1.674],[0,0],[1.218,-0.497],[0,0],[0.709,-3.236]],"v":[[0.182,-18.266],[4.538,-13.106],[7.984,-11.707],[14.703,-12.371],[18.491,-6.286],[14.931,-0.55],[14.666,3.16],[17.373,9.345],[12.757,14.829],[6.201,13.216],[2.59,14.109],[-2.455,18.596],[-9.096,15.9],[-9.588,9.166],[-11.554,6.009],[-17.38,2.596],[-16.868,-4.553],[-10.616,-7.101],[-8.221,-9.947],[-6.775,-16.542]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1206.516,732.392]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.33,1.267],[0,0],[2.051,-0.508],[0.275,-0.649],[0,0],[1.436,-0.646],[0,0],[-0.031,-1.298],[-1.672,-0.892],[0,0],[0.176,-2.221],[0,0],[-1.776,-0.141],[-0.891,1.092],[0,0],[-0.683,-0.412],[0,0],[-0.48,0.99],[0.544,1.607],[0,0],[-0.823,1.365],[0,0],[1.433,1.096],[1.162,0.003]],"o":[[0,0],[-1.33,-1.268],[0,0],[-2.051,0.508],[-0.275,0.648],[0,0],[-1.437,0.646],[0,0],[0.031,1.299],[1.672,0.892],[0,0],[-0.176,2.22],[0,0],[1.776,0.14],[0.891,-1.091],[0,0],[0.682,0.411],[0,0],[0.481,-0.989],[-0.543,-1.607],[0,0],[0.823,-1.365],[0,0],[-1.433,-1.097],[-1.162,-0.002]],"v":[[6.892,-11.449],[4.065,-13.308],[-0.126,-18.511],[-3.951,-19.306],[-6.828,-16.271],[-8.587,-8.724],[-11.53,-6.544],[-17.31,-4.097],[-19.299,-0.992],[-17.429,3.044],[-11.218,6.441],[-9.654,9.827],[-8.951,16.184],[-6.635,19.674],[-1.643,18.147],[3.082,13.784],[6.533,13.656],[12.987,15.105],[16.92,13.405],[17.27,9.545],[14.483,2.979],[14.696,-0.267],[19.085,-7.159],[17.897,-10.783],[14.107,-12.022]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1206.661,732.158]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":40,"op":50,"st":0},{"ind":32,"ty":4,"nm":"s","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[5,134,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.137,-2.531],[0,0],[-1.309,0.129],[0,0],[1.747,-2.815],[0,0],[-0.528,-1.205],[0,0],[3.216,0.791],[0,0],[0.983,-0.874],[0,0],[0.241,3.304],[0,0],[1.135,0.665],[0,0],[-3.067,1.25],[0,0],[-0.281,1.285],[0,0]],"o":[[0,0],[0.848,1.005],[0,0],[3.296,-0.326],[0,0],[-0.694,1.118],[0,0],[1.328,3.035],[0,0],[-1.277,-0.315],[0,0],[-2.476,2.201],[0,0],[-0.096,-1.311],[0,0],[-2.858,-1.674],[0,0],[1.218,-0.497],[0,0],[0.709,-3.236]],"v":[[0.182,-18.266],[4.538,-13.106],[7.984,-11.707],[14.703,-12.371],[18.491,-6.287],[14.931,-0.551],[14.666,3.16],[17.373,9.345],[12.757,14.829],[6.201,13.215],[2.59,14.109],[-2.455,18.595],[-9.096,15.9],[-9.588,9.165],[-11.554,6.009],[-17.38,2.595],[-16.868,-4.553],[-10.616,-7.102],[-8.221,-9.947],[-6.775,-16.543]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1003.018,457.183]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.33,1.267],[0,0],[2.051,-0.508],[0.275,-0.649],[0,0],[1.436,-0.646],[0,0],[-0.031,-1.298],[-1.672,-0.892],[0,0],[0.176,-2.221],[0,0],[-1.776,-0.141],[-0.891,1.092],[0,0],[-0.683,-0.412],[0,0],[-0.48,0.99],[0.544,1.607],[0,0],[-0.823,1.365],[0,0],[1.433,1.096],[1.162,0.003]],"o":[[0,0],[-1.33,-1.268],[0,0],[-2.051,0.508],[-0.275,0.648],[0,0],[-1.437,0.646],[0,0],[0.031,1.299],[1.673,0.892],[0,0],[-0.176,2.22],[0,0],[1.776,0.14],[0.891,-1.091],[0,0],[0.682,0.411],[0,0],[0.481,-0.989],[-0.543,-1.607],[0,0],[0.823,-1.365],[0,0],[-1.433,-1.097],[-1.161,-0.002]],"v":[[6.892,-11.449],[4.065,-13.308],[-0.126,-18.511],[-3.951,-19.306],[-6.828,-16.271],[-8.587,-8.724],[-11.53,-6.544],[-17.31,-4.097],[-19.299,-0.992],[-17.429,3.044],[-11.218,6.441],[-9.654,9.827],[-8.951,16.184],[-6.635,19.674],[-1.643,18.147],[3.082,13.785],[6.533,13.656],[12.987,15.105],[16.92,13.405],[17.27,9.545],[14.483,2.979],[14.696,-0.267],[19.085,-7.159],[17.897,-10.783],[14.107,-12.022]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1003.163,456.949]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":40,"op":50,"st":0},{"ind":33,"ty":4,"nm":"s","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[183,-251,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.137,-2.531],[0,0],[-1.309,0.129],[0,0],[1.747,-2.815],[0,0],[-0.528,-1.205],[0,0],[3.216,0.791],[0,0],[0.983,-0.874],[0,0],[0.241,3.304],[0,0],[1.135,0.665],[0,0],[-3.067,1.25],[0,0],[-0.281,1.285],[0,0]],"o":[[0,0],[0.848,1.005],[0,0],[3.296,-0.326],[0,0],[-0.694,1.118],[0,0],[1.328,3.035],[0,0],[-1.277,-0.315],[0,0],[-2.476,2.201],[0,0],[-0.096,-1.312],[0,0],[-2.858,-1.674],[0,0],[1.218,-0.497],[0,0],[0.709,-3.236]],"v":[[0.182,-18.266],[4.538,-13.107],[7.984,-11.708],[14.703,-12.372],[18.491,-6.287],[14.931,-0.551],[14.666,3.159],[17.373,9.344],[12.757,14.828],[6.201,13.215],[2.59,14.109],[-2.455,18.595],[-9.096,15.899],[-9.588,9.165],[-11.554,6.008],[-17.38,2.595],[-16.868,-4.554],[-10.616,-7.102],[-8.221,-9.948],[-6.775,-16.543]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[826.073,843.483]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.33,1.267],[0,0],[2.051,-0.508],[0.275,-0.649],[0,0],[1.436,-0.646],[0,0],[-0.031,-1.298],[-1.672,-0.892],[0,0],[0.176,-2.221],[0,0],[-1.776,-0.141],[-0.891,1.092],[0,0],[-0.683,-0.411],[0,0],[-0.48,0.99],[0.544,1.607],[0,0],[-0.823,1.365],[0,0],[1.433,1.096],[1.162,0.003]],"o":[[0,0],[-1.33,-1.268],[0,0],[-2.051,0.508],[-0.275,0.648],[0,0],[-1.437,0.646],[0,0],[0.031,1.299],[1.673,0.892],[0,0],[-0.176,2.22],[0,0],[1.776,0.14],[0.891,-1.091],[0,0],[0.682,0.412],[0,0],[0.481,-0.989],[-0.543,-1.607],[0,0],[0.823,-1.365],[0,0],[-1.433,-1.097],[-1.162,-0.002]],"v":[[6.892,-11.449],[4.065,-13.308],[-0.126,-18.511],[-3.951,-19.306],[-6.828,-16.271],[-8.587,-8.724],[-11.53,-6.544],[-17.31,-4.097],[-19.299,-0.992],[-17.429,3.044],[-11.218,6.441],[-9.654,9.827],[-8.951,16.184],[-6.635,19.674],[-1.643,18.147],[3.082,13.784],[6.533,13.655],[12.987,15.105],[16.92,13.405],[17.27,9.545],[14.483,2.979],[14.696,-0.267],[19.085,-7.159],[17.897,-10.783],[14.107,-12.022]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[826.218,843.248]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":40,"op":50,"st":0},{"ind":34,"ty":4,"nm":"s","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-24,-71,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.887,-13.663]],"o":[[14.055,2.969],[0,0]],"v":[[-12.203,-13.299],[12.203,13.299]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1022.756,676.426]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-13.603,2.79]],"o":[[2.906,-13.951],[0,0]],"v":[[-11.693,13.585],[11.693,-13.584]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1046.801,676.14]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.887,13.662]],"o":[[-14.055,-2.969],[0,0]],"v":[[12.472,11.971],[-12.472,-11.971]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1046.023,650.585]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[13.603,-2.79]],"o":[[-2.906,13.951],[0,0]],"v":[[11.426,-12.251],[-11.425,12.251]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1021.978,650.875]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.518,1.139],[2.755,3.369],[0.956,4.707],[0.234,-0.024],[4.601,-4.339],[4.891,-1.655],[-4.14,-4.891],[-1.773,-6.039],[-0.293,0.019],[-2.404,4.223],[-7.336,2.215],[-0.049,0.218]],"o":[[-3.961,-1.792],[-2.999,-3.669],[-0.217,0.049],[-0.438,6.266],[-3.404,3.211],[5.775,1.396],[4.201,4.965],[0.267,-0.056],[0.658,-4.272],[3.85,-6.766],[0.022,-0.223],[-2.523,-0.434]],"v":[[15.656,-4.367],[5.309,-12.227],[-0.689,-25.093],[-1.363,-24.98],[-9.593,-8.044],[-23.102,-1.03],[-7.773,8.232],[0.268,25.093],[0.61,24.984],[5.448,12.271],[23.081,-1.535],[22.804,-1.808]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1034.497,664.127]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":42,"op":52,"st":0},{"ind":35,"ty":4,"nm":"s","parent":8,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[103,-177,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.887,-13.663]],"o":[[14.055,2.969],[0,0]],"v":[[-12.203,-13.299],[12.203,13.299]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[895.756,782.426]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-13.603,2.79]],"o":[[2.906,-13.951],[0,0]],"v":[[-11.693,13.585],[11.693,-13.584]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.801,782.14]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[2.887,13.662]],"o":[[-14.055,-2.969],[0,0]],"v":[[12.471,11.971],[-12.472,-11.971]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.023,756.585]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[13.603,-2.79]],"o":[[-2.906,13.951],[0,0]],"v":[[11.426,-12.251],[-11.425,12.251]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[894.978,756.875]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.518,1.139],[2.755,3.369],[0.957,4.707],[0.234,-0.024],[4.602,-4.339],[4.891,-1.655],[-4.14,-4.891],[-1.772,-6.039],[-0.293,0.019],[-2.403,4.223],[-7.336,2.215],[-0.049,0.218]],"o":[[-3.961,-1.792],[-2.999,-3.669],[-0.217,0.049],[-0.438,6.266],[-3.404,3.211],[5.776,1.396],[4.201,4.965],[0.268,-0.056],[0.658,-4.272],[3.85,-6.766],[0.022,-0.223],[-2.522,-0.434]],"v":[[15.656,-4.367],[5.309,-12.227],[-0.689,-25.093],[-1.363,-24.98],[-9.593,-8.044],[-23.102,-1.03],[-7.773,8.232],[0.268,25.093],[0.61,24.984],[5.448,12.271],[23.081,-1.535],[22.804,-1.808]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[907.497,770.127]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":45,"op":55,"st":2},{"ind":36,"ty":4,"nm":"h","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[75,-146,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.398],[4.398,0],[0,4.398],[-4.398,0]],"o":[[0,4.398],[-4.398,0],[0,-4.398],[4.398,0]],"v":[[7.963,0],[0,7.963],[-7.963,0],[0,-7.963]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[934.796,738.397]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-9.856],[9.458,0],[0,9.856],[-9.458,0]],"o":[[0,9.856],[-9.458,0],[0,-9.856],[9.458,0]],"v":[[17.125,0],[0,17.846],[-17.125,0],[0,-17.846]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[932.888,738.574]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.357],[4.095,0],[0,4.725],[-4.096,0]],"o":[[0,4.378],[-4.096,0],[0,-4.634],[4.095,0]],"v":[[7.963,0.098],[0.068,7.963],[-7.963,0],[0.068,-7.963]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[934.796,738.397]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.031],[4.032,0],[0,4.031],[-4.031,0]],"o":[[0,4.031],[-4.031,0],[0,-4.031],[4.032,0]],"v":[[7.299,-0.001],[-0.001,7.299],[-7.3,-0.001],[-0.001,-7.299]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[933.962,738.702]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-9.529],[9.162,0],[0,9.529],[-9.162,0]],"o":[[0,9.529],[-9.162,0],[0,-9.529],[9.162,0]],"v":[[17.125,-0.177],[-0.083,17.846],[-17.125,-0.177],[-0.083,-17.845]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[932.888,738.574]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":37,"ty":4,"nm":"h","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[77,-146,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.016,-3.878]],"o":[[5.016,-1.856],[0,0]],"v":[[-7.524,-0.588],[7.524,2.444]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[929.987,753.851]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.731,-4.4]],"o":[[1.774,10.592],[0,0]],"v":[[-4.323,-10.629],[4.323,10.629]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[945.755,733.21]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.781,6.685]],"o":[[4.838,-2.979],[0,0]],"v":[[-4.214,7.249],[4.214,-7.248]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.522,729.829]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-11.348,-11.45],[5.119,-5.074],[11.048,11.146],[16.289,12.664]],"o":[[22.889,23.251],[11.348,11.449],[-5.119,5.073],[-11.047,-11.147],[0,0]],"v":[[-20.161,-31.188],[21.382,-0.539],[23.227,24.845],[-1.323,20.042],[-32.731,-18.731]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[970.24,775.026]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[14.744,-6.517],[2.914,6.592],[-14.353,6.345],[-17.64,10.701]],"o":[[-29.886,13.09],[-14.744,6.518],[-2.914,-6.592],[14.354,-6.346],[0,0]],"v":[[35.368,-9.107],[-8.083,18.773],[-32.455,11.443],[-19.211,-9.778],[28.213,-25.292]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[887.094,762.369]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,16.12],[-7.208,0],[0,-15.694],[-2.655,-20.461]],"o":[[0.111,-32.627],[0,-16.12],[7.207,0],[0,15.693],[0,0]],"v":[[-7.374,35.17],[-15.306,-15.843],[1.253,-35.171],[15.307,-14.477],[10.322,35.17]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[931.11,687.411]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-9.468,-12.012],[-4.525,-2.95],[-6.391,8.121],[3.693,4.101],[2.867,2.283],[2.387,1.824],[0,0],[0,0]],"o":[[7.57,-2.202],[3.264,7.733],[4.524,2.951],[6.39,-8.121],[-3.692,-4.101],[-2.867,-2.284],[-2.387,-1.824],[0,0],[0,0]],"v":[[-38.034,-19.5],[-10.472,0.539],[11.962,27.967],[31.644,26.592],[32.603,6.389],[24.931,-0.95],[3.06,-13.607],[-13.692,-28.254],[-30.464,-34.713]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[962.937,771.79]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[8.353,-0.835],[4.437,-3.08],[-5.116,-8.979],[-5.189,1.876],[-3.195,1.796],[-2.589,1.525],[-5.172,1.795],[0,0]],"o":[[0,0],[-8.352,0.836],[-4.437,3.08],[5.116,8.978],[5.19,-1.876],[3.194,-1.795],[9.339,-5.607],[0,0],[0,0]],"v":[[24.733,-24.106],[3.732,-14.844],[-28.971,-5.03],[-35.877,15.128],[-16.755,22.106],[-7.066,18.513],[11.511,3.018],[33.422,-8.217],[40.993,-23.502]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[891.481,760.579]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.253,29.44],[0.995,5.309],[10.285,-0.995],[0.411,-5.503],[-0.332,-3.65],[-0.331,-2.986],[0,0],[0,0]],"o":[[0,0],[2.655,-7.963],[-0.996,-5.309],[-10.286,0.996],[-0.411,5.503],[0.332,3.649],[5.569,35.238],[0,0],[0,0]],"v":[[16.969,45.869],[9.486,3.568],[13.8,-31.602],[-0.799,-44.874],[-16.062,-31.602],[-16.062,-20.984],[-10.09,3.568],[-16.969,39.411],[0.196,39.411]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[932.277,697.667]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":38,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.479,1.659],[4.479,-1.659]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1036.159,651.134]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.325,7.335],[2.325,-7.335]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1023.057,637.495]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.038,-4.049],[1.038,4.049]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.689,717.29]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.774,-7.576],[0.774,7.576]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.072,725.07]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4.645,-5.143],[-4.645,5.143]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[988.879,713.899]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.853,-0.829],[-7.853,0.83]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.474,678.805]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.475,5.812],[-6.475,-5.811]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.694,644.438]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.953,1.294],[-7.953,-1.294]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.912,660.899]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.878,7.12],[2.878,-7.12]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1001.042,724.724]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.081,8.57],[-3.081,-8.57]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1006.038,632.61]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.791,3.087],[7.791,-3.087]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.079,694.917]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":7,"st":0},{"ind":39,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.791,3.1]],"o":[[-0.79,-3.1],[0,0]],"v":[[1.186,4.651],[-1.186,-4.65]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.154,717.769]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.572,5.215]],"o":[[-0.571,-5.215],[0,0]],"v":[[0.857,7.823],[-0.857,-7.823]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1018.215,725.065]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.042,7.306],[3.041,-7.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1000.26,724.191]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.155,3.343]],"o":[[3.156,-3.343],[0,0]],"v":[[-4.733,5.014],[4.734,-5.014]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[988.646,712.59]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.766,3.026],[7.766,-3.026]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.054,693.638]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.08,0.535]],"o":[[5.08,-0.535],[0,0]],"v":[[-7.62,0.803],[7.62,-0.803]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.571,677.81]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.219,-1.199]],"o":[[-3.218,1.199],[0,0]],"v":[[4.828,-1.798],[-4.828,1.798]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.177,652.047]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.7,-4.695]],"o":[[-1.7,4.696],[0,0]],"v":[[2.55,-7.044],[-2.55,7.044]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1024.035,637.84]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.697,-5.769]],"o":[[1.697,5.769],[0,0]],"v":[[-2.545,-8.653],[2.545,8.653]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1007.087,632.282]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.362,-3.998]],"o":[[4.363,3.998],[0,0]],"v":[[-6.544,-5.996],[6.544,5.997]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.919,643.492]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.417,-0.993]],"o":[[5.417,0.993],[0,0]],"v":[[-8.126,-1.489],[8.126,1.489]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.839,659.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":7,"op":8,"st":0},{"ind":40,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.215,-4.814],[1.215,4.813]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1031.072,718.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.796,-8.146],[0.796,8.146]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1016.246,725.64]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.128,-7.241],[-3.128,7.241]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[999.136,723.526]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[5.374,-5.319],[-5.374,5.319]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[987.936,711.05]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.636,2.969],[7.636,-2.969]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[982.562,691.948]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.58,-0.387],[-7.58,0.386]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.748,676.188]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8.005,1.923],[-8.006,-1.923]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[984.574,657.948]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.977,1.818],[4.977,-1.819]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.666,653.662]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.779,6.854],[2.779,-6.854]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1025.836,639.26]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.989,-8.776],[1.989,8.776]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1008.789,632.405]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.255,6.514],[-6.255,-6.514]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[993.31,641.664]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":8,"op":9,"st":0},{"ind":41,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.353,-2.221],[1.353,2.22]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.389,711.679]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.323,-6.161],[1.323,6.161]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1026.705,721.334]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.64,-8.829],[-0.64,8.829]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1010.138,726.323]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.618,7.148],[3.618,-7.148]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[995.312,720.39]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.48,4.253],[6.48,-4.253]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[985.385,704.503]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.673,-2.302],[-7.673,2.302]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[981.206,686.676]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.475,0.488],[-7.475,-0.488]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[981.404,669.44]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.588,3.638],[-7.588,-3.638]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[987.055,651.843]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-5.403,0.885],[5.403,-0.885]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1038.742,659.097]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.332,4.776],[3.333,-4.776]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1030.535,643.402]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1015.45,641.18],[1015.45,625.096]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4.716,7.889],[-4.717,-7.889]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[998.24,636.548]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":9,"op":10,"st":0},{"ind":42,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.952,-4.203],[0.952,4.203]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1034.291,715.881]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.979,-6.984],[0.979,6.984]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1021.475,724.274]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.498,-7.569],[-2.498,7.57]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.54,725.759]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.697,5.621],[4.697,-5.62]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[990.615,715.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.867,3.537],[7.867,-3.537]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.827,697.397]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.56,-1.222],[-7.56,1.221]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.767,681.101]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.791,1.089],[-7.791,-1.089]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.078,663.283]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.894,5.473],[-6.894,-5.473]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[989.972,646.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.726,8.524],[-3.726,-8.525]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.926,633.621]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.708,2.368],[4.708,-2.368]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1035.243,648.766]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.992,7.469],[1.992,-7.469]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1021.065,635.629]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":10,"op":11,"st":0},{"ind":43,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.216,-1.215]],"o":[[-3.216,1.215],[0,0]],"v":[[4.824,-1.823],[-4.825,1.823]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1036.38,650.589]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.476,-5.124]],"o":[[-1.476,5.124],[0,0]],"v":[[2.214,-7.686],[-2.214,7.686]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1022.414,636.844]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-2.129,-5.705]],"o":[[2.128,5.704],[0,0]],"v":[[-3.192,-8.557],[3.193,8.557]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1005.399,632.774]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.634,-5.964],[6.634,5.964]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[990.867,645.17]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-8.203,-1.328],[8.203,1.328]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.491,661.954]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.609,1.148],[7.608,-1.148]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.719,679.953]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.702,3.25],[7.703,-3.25]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.167,695.88]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.895,5.492],[4.895,-5.492]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[989.59,714.249]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.63,2.816]],"o":[[-0.63,-2.816],[0,0]],"v":[[0.944,4.224],[-0.945,-4.224]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1033.347,717.115]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.83,7.427],[-0.83,-7.427]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.902,724.717]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.812,7.521],[2.812,-7.521]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1002.207,725.125]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":11,"op":14,"st":0},{"ind":44,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.952,-4.203],[0.952,4.203]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1034.291,715.881]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.979,-6.984],[0.979,6.984]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1021.475,724.274]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.498,-7.569],[-2.498,7.57]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.54,725.759]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.697,5.621],[4.697,-5.62]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[990.615,715.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.867,3.537],[7.867,-3.537]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.827,697.397]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.56,-1.222],[-7.56,1.221]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.767,681.101]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.791,1.089],[-7.791,-1.089]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.078,663.283]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.894,5.473],[-6.894,-5.473]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[989.972,646.37]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.726,8.524],[-3.726,-8.525]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.926,633.621]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.708,2.368],[4.708,-2.368]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1035.243,648.766]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.992,7.469],[1.992,-7.469]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1021.065,635.629]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":14,"op":15,"st":1},{"ind":45,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.353,-2.221],[1.353,2.22]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.389,711.679]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.323,-6.161],[1.323,6.161]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1026.705,721.334]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.64,-8.829],[-0.64,8.829]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1010.138,726.323]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.618,7.148],[3.618,-7.148]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[995.312,720.39]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.48,4.253],[6.48,-4.253]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[985.385,704.503]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.673,-2.302],[-7.673,2.302]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[981.206,686.676]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.475,0.488],[-7.475,-0.488]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[981.404,669.44]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.588,3.638],[-7.588,-3.638]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[987.055,651.843]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-5.403,0.885],[5.403,-0.885]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1038.742,659.097]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.332,4.776],[3.333,-4.776]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1030.535,643.402]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1015.45,641.18],[1015.45,625.096]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4.716,7.889],[-4.717,-7.889]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[998.24,636.548]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":15,"op":16,"st":1},{"ind":46,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.215,-4.814],[1.215,4.813]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1031.072,718.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.796,-8.146],[0.796,8.146]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1016.246,725.64]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.128,-7.241],[-3.128,7.241]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[999.136,723.526]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[5.374,-5.319],[-5.374,5.319]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[987.936,711.05]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.636,2.969],[7.636,-2.969]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[982.562,691.948]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.58,-0.387],[-7.58,0.386]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.748,676.188]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8.005,1.923],[-8.006,-1.923]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[984.574,657.948]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.977,1.818],[4.977,-1.819]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.666,653.662]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.779,6.854],[2.779,-6.854]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1025.836,639.26]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.989,-8.776],[1.989,8.776]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1008.789,632.405]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.255,6.514],[-6.255,-6.514]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[993.31,641.664]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":16,"op":17,"st":1},{"ind":47,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.791,3.1]],"o":[[-0.79,-3.1],[0,0]],"v":[[1.186,4.651],[-1.186,-4.65]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.154,717.769]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.572,5.215]],"o":[[-0.571,-5.215],[0,0]],"v":[[0.857,7.823],[-0.857,-7.823]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1018.215,725.065]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.042,7.306],[3.041,-7.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1000.26,724.191]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.155,3.343]],"o":[[3.156,-3.343],[0,0]],"v":[[-4.733,5.014],[4.734,-5.014]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[988.646,712.59]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.766,3.026],[7.766,-3.026]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.054,693.638]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.08,0.535]],"o":[[5.08,-0.535],[0,0]],"v":[[-7.62,0.803],[7.62,-0.803]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.571,677.81]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.219,-1.199]],"o":[[-3.218,1.199],[0,0]],"v":[[4.828,-1.798],[-4.828,1.798]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.177,652.047]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.7,-4.695]],"o":[[-1.7,4.696],[0,0]],"v":[[2.55,-7.044],[-2.55,7.044]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1024.035,637.84]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.697,-5.769]],"o":[[1.697,5.769],[0,0]],"v":[[-2.545,-8.653],[2.545,8.653]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1007.087,632.282]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.362,-3.998]],"o":[[4.363,3.998],[0,0]],"v":[[-6.544,-5.996],[6.544,5.997]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.919,643.492]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.417,-0.993]],"o":[[5.417,0.993],[0,0]],"v":[[-8.126,-1.489],[8.126,1.489]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.839,659.713]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":17,"op":18,"st":1},{"ind":48,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4.479,1.659],[4.479,-1.659]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1036.159,651.134]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.325,7.335],[2.325,-7.335]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1023.057,637.495]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.038,-4.049],[1.038,4.049]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.689,717.29]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.774,-7.576],[0.774,7.576]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.072,725.07]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4.645,-5.143],[-4.645,5.143]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[988.879,713.899]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.853,-0.829],[-7.853,0.83]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[980.474,678.805]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.475,5.812],[-6.475,-5.811]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.694,644.438]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.953,1.294],[-7.953,-1.294]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.912,660.899]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2.878,7.12],[2.878,-7.12]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1001.042,724.724]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.081,8.57],[-3.081,-8.57]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1006.038,632.61]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-7.791,3.087],[7.791,-3.087]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[983.079,694.917]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":18,"op":38,"st":0},{"ind":49,"ty":4,"nm":"d","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-14,-92,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.665,0.957],[-6.664,-0.957]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1027.203,706.13]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.665,0.957],[-6.664,-0.957]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1029.857,659.181]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.761],[3.769,0],[0,5.761],[-3.769,0]],"o":[[0,5.761],[-3.769,0],[0,-5.761],[3.769,0]],"v":[[6.825,0],[0,10.431],[-6.824,0],[0,-10.431]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1037.321,683.429]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-13.072],[8.552,0],[0,13.072],[-8.551,0]],"o":[[0,13.072],[-8.551,0],[0,-13.072],[8.552,0]],"v":[[15.484,0],[0,23.668],[-15.484,0],[0,-23.668]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1036.521,683.806]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,13.071],[-8.552,0]],"o":[[-8.552,0],[0,-13.072],[0,0]],"v":[[7.742,23.668],[-7.742,0],[7.742,-23.668]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1015.45,681.892]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.436],[3.543,0],[0,5.436],[-3.543,0]],"o":[[0,5.436],[-3.543,0],[0,-5.436],[3.543,0]],"v":[[6.71,-0.018],[0.295,10.414],[-6.711,0.022],[0.295,-10.414]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1037.246,683.446]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[3.273,-14.001],[-5.747,-3.465],[0,0],[-4.162,21.333]],"o":[[0,0],[0,0],[-3.546,15.293],[0,0],[0,0],[1.355,-12.273]],"v":[[14.16,-22.341],[2.215,-24.111],[-10.614,-8.184],[-0.882,22.341],[11.506,24.111],[2.658,-5.53]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1019.179,682.323]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-12.736],[8.612,0],[0,12.736],[-8.613,0]],"o":[[0,12.736],[-8.613,0],[0,-12.736],[8.612,0]],"v":[[15.969,0.078],[0.355,23.867],[-15.969,0.078],[-0.374,-23.867]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[1,0.878,0.839,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1036.036,683.738]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":50,"ty":4,"nm":"d","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[4,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.583,-13.275]],"o":[[2.542,13.252],[0,0]],"v":[[0.512,-19.896],[-3.054,19.896]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1046.553,685.835]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,28.82],[-18.576,0]],"o":[[-21.899,0],[0,-27.109],[0,0]],"v":[[18.914,55.778],[-18.914,0.041],[14.936,-55.777]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[991.864,679.407]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[16.43,0],[0,30.982],[-23.579,0],[-4.672,-24.325]],"o":[[-7.138,17.878],[-23.579,0],[0,-30.982],[19.963,0],[0,0]],"v":[[38.479,26.023],[0.648,56.097],[-42.046,0],[0.648,-56.097],[42.046,-13.768]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1005.02,679.708]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-21.291,9.809],[10.312,-35.082],[-34.418,3.115],[2.873,51.821],[0,0]],"o":[[0,0],[-9.475,35.945],[-6.259,-0.27],[0.12,-0.832],[0,0]],"v":[[17.567,-57.392],[-17.659,-20.046],[27.134,54.277],[-10.362,-2.742],[-8.838,-17.97]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[983.312,681.355]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.193,-30.602],[20.464,-2.017],[0,30.602],[-20.89,0]],"o":[[-0.188,29.712],[-20.79,2.049],[0,-30.602],[20.89,0]],"v":[[37.728,-0.737],[-0.096,54.673],[-37.921,-0.737],[-2.691,-56.721]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1010.542,680.406]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":51,"ty":4,"nm":"S","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":-1},"p":{"a":0,"k":[123,-275,0],"l":2},"a":{"a":0,"k":[0,0,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[84.5,50],[154.5,12],[215.5,368],[-60,378.5],[-57,107]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"S"}],"ip":0,"op":64,"st":0},{"ind":52,"ty":4,"nm":"b","parent":14,"tt":2,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[123,-278,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.14,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[-37.335,-28.415],[-37.335,15.542],[-22.69,25.873],[37.336,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[936.187,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.291,2.367],[0,0],[0,1.835],[0,0],[7.173,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[2.54,-0.905],[0,0],[0.879,-1.611],[0,0],[0,-7.67],[0,0],[-4.266,1.613],[0,0],[0,0]],"v":[[-6.066,107.801],[58.212,84.916],[64.161,79.836],[79.398,51.901],[80.737,46.65],[80.737,-94.83],[65.893,-105.089],[-73.649,-52.33],[-80.737,-42.073],[-80.737,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[979.588,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.948,0],[0,5.222],[4.947,0]],"o":[[0,5.222],[4.947,0],[0,-5.223],[-4.948,0]],"v":[[-8.958,0],[0,9.456],[8.958,0],[0,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1024.823,530.913]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.222],[4.948,0]],"o":[[0,5.222],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[994.409,543.632]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.223],[4.948,0]],"o":[[0,5.223],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[959.459,556.904]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.223],[4.948,0]],"o":[[0,5.223],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[922.63,571.061]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.223],[-4.948,0]],"o":[[0,5.223],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.958,0],[0,9.456],[-8.959,0],[0,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[883.81,581.236]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.223],[-4.948,0]],"o":[[0,5.223],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.959,0],[0.001,9.456],[-8.958,0],[0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[847.091,567.964]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.222],[-4.948,0]],"o":[[0,5.222],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.959,0],[0.001,9.456],[-8.958,0],[0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[817.008,549.826]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[24.097,8.032],[-24.098,-8.032]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[874.007,510.924]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[6.025,-30.925],[-6.024,-0.402],[-2.812,30.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[872.802,510.522]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[4.82,-30.925],[24.098,8.434],[-4.016,30.925],[-24.097,-7.631]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[874.007,510.522]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-24.097,8.032],[24.097,-8.032]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[949.936,491.557]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-6.024,-30.925],[6.024,-0.402],[2.812,30.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[951.141,491.155]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-4.819,-30.925],[-24.097,8.434],[4.017,30.925],[24.098,-7.631]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[949.936,491.155]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.14,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[-37.335,-28.415],[-37.335,15.542],[-22.69,25.873],[37.336,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[936.187,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.291,2.367],[0,0],[0,1.835],[0,0],[7.173,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[2.54,-0.905],[0,0],[0.879,-1.611],[0,0],[0,-7.67],[0,0],[-4.266,1.613],[0,0],[0,0]],"v":[[-6.066,107.801],[58.212,84.916],[64.161,79.836],[79.398,51.901],[80.737,46.65],[80.737,-94.83],[65.893,-105.089],[-73.649,-52.33],[-80.737,-42.073],[-80.737,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[979.588,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.511,1.186],[0,0],[0.014,-5.253],[0,0],[-0.697,-1.119],[0,0],[-1.35,-0.593],[0,0],[0.024,5.187],[0,0]],"o":[[0,0],[-0.013,-2.719],[0,0],[-4.851,-2.292],[0,0],[-0.004,1.31],[0,0],[0.768,1.233],[0,0],[4.855,2.13],[0,0],[0,0]],"v":[[36.582,69.522],[36.067,-71.032],[31.943,-77.414],[-25.981,-104.779],[-36.488,-98.383],[-36.892,56.11],[-35.832,59.825],[-21.818,82.338],[-18.567,85.141],[26.552,104.94],[36.872,98.409],[36.734,69.522]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[831.343,714.552]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[6.464,0],[0,8.344],[-4.924,2.734]],"o":[[-4.668,2.091],[-15.026,0],[0,-4.172],[0,0]],"v":[[22.139,9.552],[5.069,12.895],[-22.138,-2.213],[-14.169,-12.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[808.179,817.41]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.261,0],[0,7.513],[-0.705,1.437]],"o":[[0.516,1.249],[0,7.513],[-10.262,0],[0,-1.614],[0,0]],"v":[[17.786,-8.448],[18.58,-4.501],[0,9.102],[-18.581,-4.501],[-17.492,-9.102]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[812.805,836.023]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-3.305],[15.026,0],[4.978,3.561]],"o":[[3.243,2.487],[0,8.344],[-8.748,0],[0,0]],"v":[[19.204,-11.979],[24.358,-3.129],[-2.849,11.979],[-24.358,6.125]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.871,798.861]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.261,0],[0,7.513],[-0.705,1.437]],"o":[[0.516,1.249],[0,7.513],[-10.262,0],[0,-1.614],[0,0]],"v":[[17.786,-8.448],[18.58,-4.501],[0,9.102],[-18.581,-4.501],[-17.492,-9.102]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1029.579,816.557]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.262,0],[0,7.513],[-0.704,1.437]],"o":[[1.025,0.937],[0,7.513],[-10.262,0],[0,-1.615],[0,0]],"v":[[17.133,-9.102],[18.581,-4.501],[-0.001,9.102],[-18.581,-4.501],[-17.492,-9.101]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[886.686,868.317]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-2.311],[14.843,0],[0,8.613],[-1.156,1.076]],"o":[[1.554,1.973],[0,8.613],[-14.843,0],[0,-1.077],[0,0]],"v":[[24.455,-11.036],[26.875,-4.558],[0,11.036],[-26.875,-4.558],[-25.166,-9.239]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[886.64,851.548]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[883.81,845.788],[883.81,778.765]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[883.81,778.765],[883.81,630.937]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-41.838,-20.679],[0,0],[-13.667,5.067],[0,0],[45.715,17.404],[6.243,0.052]],"o":[[0,0],[-43.889,15.871],[0,0],[13.068,6.458],[0,0],[45.865,-17.004],[-5.927,-2.256],[0,0]],"v":[[-48.32,-39.792],[-53.245,-38.011],[-58.703,59.297],[-57.951,59.669],[-16.064,61.849],[54.392,35.727],[54.825,-63.452],[36.421,-66.916]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.482,494.565]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[5.964,-2.156],[0,0]],"o":[[-6.243,-0.052],[0,0],[0,0]],"v":[[42.371,-13.536],[23.911,-10.381],[-42.37,13.588]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[913.533,441.185]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-22.66,-11.2],[0,0],[-7.403,2.745],[0,0],[24.759,9.426],[0,0]],"o":[[0,0],[-23.77,8.596],[0,0],[7.078,3.498],[0,0],[24.84,-9.21],[0,0],[0,0]],"v":[[-92.612,-34.094],[-110.589,-27.593],[-113.545,25.109],[-52.348,55.356],[-29.661,56.536],[111.212,4.308],[111.446,-49.407],[85.514,-59.28]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[923.265,544.66]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-10.475,-5.177],[0,0],[-3.422,1.268],[0,0],[11.446,4.357],[0,0]],"o":[[0,0],[-10.989,3.973],[0,0],[3.272,1.617],[0,0],[11.483,-4.258],[0,0],[0,0]],"v":[[-130.762,-30.138],[-147.021,-24.258],[-148.388,0.104],[-48.788,49.332],[-38.301,49.878],[147.31,-18.937],[147.418,-43.768],[128.039,-51.146]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[925.005,580.174]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-17.728,-9.042],[0,0],[-13.831,5.068],[0,0],[0,22.215],[0,0]],"o":[[0,0],[0,19.9],[0,0],[13.122,6.693],[0,0],[20.858,-7.643],[0,0],[0,0]],"v":[[-146.322,-121.324],[-146.322,63.906],[-117.435,111.068],[-68.026,136.271],[-25.755,138.818],[111.596,88.488],[146.322,38.778],[146.322,-143.886]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[926.833,704.772]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.866,2.654],[0,0],[0.884,-7.078],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[-4.866,-2.655],[0,0],[-0.885,7.078],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[36.055,-65.032],[31.631,-76.534],[-27.65,-104.849],[-36.055,-98.654],[-36.498,57.511],[-21.456,84.497],[-11.281,89.806],[25.88,105.29],[33.843,105.733],[36.94,100.423]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[831.386,713.955]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-5.088,-31.084],[-23.226,8.079],[4.645,31.084],[23.225,-8.29]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[949.948,491.314]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-23.668,-6.232],[-3.135,30.669],[23.668,8.368],[5.637,-30.669]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[873.413,510.49]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-23.889],[0,0],[0,-6.194],[-9.069,-6.415],[0,0],[-9.291,3.539],[0,0],[0.442,4.424],[1.327,0.885],[0,0],[26.544,10.175],[0,0],[17.696,17.696],[18.58,-4.866],[0,0],[4.494,-21.791],[0,0],[0,0]],"o":[[0,0],[0,0],[0,6.194],[0,0],[0,0],[9.29,-3.539],[0,0],[-0.442,-4.424],[-1.327,-0.884],[0,0],[-16.147,-7.121],[0,0],[-17.696,-17.696],[-18.581,4.867],[0,0],[-4.494,21.791],[0,0],[0,0]],"v":[[-132.055,21.235],[-149.308,27.429],[-155.944,38.046],[-145.106,53.751],[-50.212,100.866],[-32.958,99.539],[151.52,30.083],[155.502,19.908],[150.193,9.29],[127.189,-0.442],[106.396,-34.507],[83.163,-43.653],[69.235,-83.613],[13.051,-98.212],[-63.484,-70.783],[-92.064,-38.664],[-94.963,-18.467],[-118.341,-10.175]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[925.616,529.033]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.205,-0.719],[6.972,-12.532],[1.409,-0.652],[12.518,-4.674],[14.678,-4.721],[7.937,-3.109],[6.008,-3.367],[-1.058,10.694],[0,1.086],[0,0],[-1.071,2.068],[-4.972,1.578],[-5.873,2.236],[-17.537,6.674],[-10.891,4.659],[-9.839,1.97],[-2.72,-0.142],[-0.908,-1.043],[-0.64,-3.923],[0,-1.229],[0,0]],"o":[[-5.824,11.718],[-0.281,1.1],[-12.146,5.623],[-14.442,5.394],[-7.146,2.298],[-6.327,2.694],[-8.814,4.938],[-0.473,-0.72],[0,0],[0,-2.878],[3.522,-6.806],[5.996,-1.902],[17.53,-6.674],[11.637,-4.427],[4.004,-1.713],[2.397,-1.257],[1.509,0.079],[3.536,0.795],[0.59,0.76],[0,0],[0.072,0.615]],"v":[[133.166,36.389],[116.586,67.576],[113.183,71.41],[75.613,85.335],[31.962,100.904],[10.648,108.511],[-8.37,114.909],[-28.313,105.78],[-28.313,100.624],[-28.313,-48.77],[-26.956,-58.636],[-13.865,-66.824],[5.085,-73.772],[56.379,-93.436],[89.317,-106.317],[114.032,-114.819],[122.735,-117.831],[127.066,-116.643],[132.388,-108.518],[133.345,-105.537],[133.345,34.385]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-11.281,-8.627],[0,0],[0,0],[-25.87,11.612],[0,0],[0,38.709],[0,0]],"o":[[0,0],[0,0],[0,0],[4.7,7.852],[0,0],[0,0],[68.939,-24.365],[0,0],[0,-34.507],[0,0]],"v":[[-14.599,-148.147],[-146.654,-121.603],[-146.654,68.184],[-132.055,100.037],[-117.01,111.318],[-66.449,138.087],[-18.58,136.535],[116.48,86.635],[145.991,37.001],[146.654,-143.502]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.004,0.502,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[927.164,704.387]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-7.806],[10.079,0],[0,6.506],[-10.078,0]],"o":[[0,6.505],[-10.078,0],[0,-6.505],[10.079,0]],"v":[[18.816,1.184],[0.567,12.964],[-18.815,0.051],[0.567,-12.964]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1029.455,812.364]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[7.9,2.803],[13.437,-4.051],[0,-0.124],[-14.455,0],[0,8.85]],"o":[[-13.097,5.033],[-0.004,0.124],[0,8.85],[14.455,0],[0,-5.83]],"v":[[13.25,-14.174],[-26.656,-0.81],[-26.671,-0.438],[-0.498,14.174],[26.67,-0.438]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1030.559,796.665]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-7.327],[10.262,0],[0,7.327],[-10.261,0]],"o":[[0,7.327],[-10.261,0],[0,-7.327],[10.262,0]],"v":[[18.581,0],[-0.001,13.266],[-18.581,0],[-0.001,-13.266]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[886.685,864.153]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-8.85],[14.763,0],[0,8.85],[-14.764,0]],"o":[[0,8.85],[-14.764,0],[0,-8.85],[14.763,0]],"v":[[26.733,0],[0,16.023],[-26.732,0],[0,-16.023]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[886.496,846.991]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[29.862,0.995],[0.664,-17.585],[0,0],[0,0],[-16.59,0.664],[1.991,5.309]],"o":[[0,0],[1.041,5.758],[0,0],[0,0],[16.59,-0.663],[0,0]],"v":[[-1.659,-17.997],[-28.203,-5.64],[-18.912,4.977],[-20.24,11.281],[-0.332,22.562],[15.788,5.115]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[814.354,822.01]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":53,"ty":4,"nm":"d","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-51,-81,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.14,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[-37.335,-28.415],[-37.335,15.542],[-22.69,25.873],[37.336,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[936.187,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.291,2.367],[0,0],[0,1.835],[0,0],[7.173,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[2.54,-0.905],[0,0],[0.879,-1.611],[0,0],[0,-7.67],[0,0],[-4.266,1.613],[0,0],[0,0]],"v":[[-6.066,107.801],[58.212,84.916],[64.161,79.836],[79.398,51.901],[80.737,46.65],[80.737,-94.83],[65.893,-105.089],[-73.649,-52.33],[-80.737,-42.073],[-80.737,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[979.588,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.019,0.073],[-0.132,0.464],[-0.341,0.659],[0,0],[-0.001,0.051],[0,0],[0,0],[4.031,1.872],[2.844,-1.312],[0,0],[0,-9.732],[0,0],[-15.484,3.982],[0,0],[0,0],[0,0]],"o":[[0.125,-0.469],[-0.004,-0.763],[0,0],[0,-0.051],[0,0],[0,0],[-0.583,-4.194],[-2.256,-0.975],[0,0],[0,0],[0,0],[0,0],[15.484,-3.982],[0,0],[0,0],[0.016,-0.073]],"v":[[79.701,38.074],[80.127,36.688],[80.672,34.544],[80.672,31.077],[80.679,30.927],[80.353,28.306],[80.353,-108.836],[73.717,-118.128],[66.196,-118.128],[-74.043,-65.482],[-80.679,-53.095],[-80.679,105.724],[-64.311,115.458],[61.329,69.891],[66.637,62.37],[79.663,38.292]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[979.973,705.556]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":54,"ty":1,"nm":"R","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.118},"t":34,"s":[1007,599,0],"to":[2.833,-2.833,0],"ti":[-2.833,2.833,0]},{"t":36,"s":[1024,582,0]}],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0,0]},"t":34,"s":[4,4,100]},{"t":36,"s":[3,4,100]}],"l":2}},"ao":0,"sw":1920,"sh":1080,"sc":"#057bd7","ip":34,"op":37,"st":0},{"ind":55,"ty":4,"nm":"d","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[93,-122,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-4.938,-2.968]],"o":[[4.937,1.179],[0,0]],"v":[[-7.406,-3.111],[7.406,3.11]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[954.811,579.157]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-0.306,-4.202]],"o":[[3.191,1.669],[0,0]],"v":[[-2.577,-4.444],[2.578,4.444]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[964.794,586.712]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.419,-0.571]],"o":[[4.978,-4.775],[0,0]],"v":[[-7.851,2.803],[7.85,-2.233]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[939.553,578.28]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[22.219,-17.923],[-22.219,17.923]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[909.484,599.006]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-8.344,6.795]],"o":[[-0.247,-8.617],[0,0]],"v":[[-5.95,11.56],[6.196,-11.56]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[881.068,628.489]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.354,-48.906]],"o":[[5.48,44.39],[0,0]],"v":[[-2.802,-70.211],[-0.552,70.211]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[970.174,661.367]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[6.791,-8.893]],"o":[[-1.327,20.088],[0,0]],"v":[[5.925,-22.07],[-5.925,22.07]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.698,753.649]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-20.127,19.405],[20.126,-19.404]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[937.646,795.124]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.69,-1.495]],"o":[[-0.018,7.359],[0,0]],"v":[[-1.324,-6.37],[1.342,6.37]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[876.443,803.123]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[6.256,2.79]],"o":[[-6.586,9.505],[0,0]],"v":[[10.387,-4.753],[-10.387,0.284]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[907.133,819.281]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-7.604,-2.352]],"o":[[4.46,4.816],[0,0]],"v":[[-9.48,-5.036],[9.48,5.037]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[887.265,814.529]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[875.119,796.754],[875.119,640.049]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.008,0.936],[0.082,1.93],[0.147,5.634],[0.279,7.708],[0.103,3.719],[0.874,2.442],[0.01,0.51],[0.01,0.2],[2.212,8.594],[3.946,1.823],[5.648,-0.728],[4.04,-3.064],[2.682,-1.719],[0.081,-0.07],[9.164,-7.212],[3.172,-3.404],[1.409,-2.826],[0.657,-3.44],[0,-0.183],[0,0],[0,-0.368],[0,0],[0.01,-0.14],[0.028,-0.407],[-3.108,-3.699],[-4.435,-1.61],[-6.78,9.474],[-0.208,0.21],[-0.27,0.261],[-13.73,13.033],[-0.065,0.12],[-1.664,3.82],[-0.156,0.359],[-0.835,4.822],[-0.428,6.69],[-0.411,13.032],[-0.499,1.172],[-0.141,0.238],[0.03,0.173]],"o":[[-0.017,-1.932],[-0.238,-5.63],[-0.201,-7.71],[-0.135,-3.72],[-0.072,-2.556],[-0.207,-0.577],[-0.029,-0.187],[-0.48,-9.058],[-2.056,-3.194],[-5.079,-2.347],[-5.184,0.667],[-2.538,1.924],[-0.074,0.07],[-8.83,7.624],[-3.276,2.579],[-1.824,2.504],[-1.624,3.257],[0.016,0.172],[0,0],[0.061,0.326],[0,0],[0,0.147],[0.055,0.355],[-0.316,4.646],[3.29,3.916],[8.754,3.177],[0.185,-0.258],[0.193,-0.275],[13.595,-13.147],[0.055,-0.119],[2.115,-3.607],[0.076,-0.351],[1.965,-4.518],[1.143,-6.61],[0.832,-13.013],[-0.421,-1.088],[0.015,-0.109],[-0.002,-0.132],[-0.158,-0.914]],"v":[[48.806,-20.064],[48.625,-25.856],[48.294,-42.76],[47.604,-65.892],[47.025,-77.048],[46.615,-84.741],[46.299,-86.373],[46.24,-86.953],[43.305,-113.537],[34.721,-120.809],[18.245,-124.325],[4.802,-116.932],[-2.573,-110.676],[-2.795,-110.465],[-30.872,-88.243],[-41.328,-78.828],[-45.881,-71.937],[-48.539,-61.287],[-48.495,-60.769],[-48.495,18.9],[-48.396,19.939],[-48.396,94.665],[-48.417,95.091],[-48.373,96.234],[-45.707,109.066],[-32.979,116.835],[-6.425,115.579],[-5.832,114.884],[-5.154,114.077],[35.487,74.453],[35.645,74.097],[40.987,62.807],[41.333,61.741],[44.788,46.429],[46.927,26.436],[48.581,-12.657],[48.596,-16.135],[48.815,-16.656],[48.773,-17.108]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[923.492,700.426]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":38,"st":0},{"ind":56,"ty":3,"nm":"a","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":42,"s":[600,540,0],"to":[60,0,0],"ti":[-60,0,0]},{"i":{"x":0.667,"y":0.887},"o":{"x":0.333,"y":0},"t":51,"s":[960,540,0],"to":[0,0,0],"ti":[-0.284,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.313},"t":52,"s":[962.455,540,0],"to":[1.399,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":56,"s":[966,540,0],"to":[-3.6,0,0],"ti":[11.213,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[950.215,540,0],"to":[-3.129,0,0],"ti":[3.41,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":61,"s":[932.371,540,0],"to":[-1.308,0,0],"ti":[9.989,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[915.207,540,0],"to":[-8.694,0,0],"ti":[0.483,0,0]},{"t":63,"s":[893,540,0]}],"l":2},"a":{"a":0,"k":[0,0,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"ip":0,"op":64,"st":0},{"ind":57,"ty":4,"nm":"S","td":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[960,540,0],"l":2},"a":{"a":0,"k":[0,0,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[432,384]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"R"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[146,137]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"R"}],"ip":0,"op":64,"st":0},{"ind":58,"ty":4,"nm":"B","parent":56,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[43.53,573.11,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-11.035,-0.167],[-3.344,-4.013],[12.205,-0.335],[0,0]],"o":[[0,0],[11.546,0.175],[4.774,5.728],[-12.205,0.334],[0,0]],"v":[[-22.922,-8.611],[-2.585,-2.424],[18.147,-4.43],[1.762,8.277],[-18.301,5.602]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1186.095,134.345]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-11.035,-0.167],[-3.344,-4.013],[12.206,-0.335],[0,0]],"o":[[0,0],[11.546,0.175],[4.774,5.728],[-12.205,0.334],[0,0]],"v":[[-20.216,-6.99],[-4.895,-2.508],[15.837,-4.514],[-0.548,8.193],[-20.611,5.517]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1188.405,143.091]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.121,-0.078],[-3.344,-4.013],[12.205,-0.334],[0,0]],"o":[[3.555,1.527],[11.546,0.175],[4.773,5.728],[-12.206,0.335],[0,0]],"v":[[-19.547,-6.122],[-4.895,-2.508],[15.838,-4.514],[-0.547,8.192],[-20.611,5.517]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1188.405,151.753]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.828,-0.088],[-3.344,-4.013],[12.205,-0.335],[0,0]],"o":[[3.674,1.736],[11.546,0.175],[4.773,5.728],[-12.205,0.334],[0,0]],"v":[[-18.713,-6.201],[-5.342,-2.508],[15.39,-4.514],[-0.995,8.193],[-20.162,5.949]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1188.853,160.415]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":1228,"st":0},{"ind":59,"ty":4,"nm":"S","td":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[960,540,0],"l":2},"a":{"a":0,"k":[0,0,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[432,384]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"R"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":4,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[1,0,0,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[146,137]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"R"}],"ip":0,"op":64,"st":0},{"ind":60,"ty":4,"nm":"B","parent":56,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[43.53,573.11,0],"l":2},"a":{"a":0,"k":[965.53,543.11,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-4.179,3.345],[-0.668,2.677],[4.178,4.68],[-1.146,1.478],[-5.684,-5.353],[-0.165,-3.174],[0.336,-1.672],[0,0],[-4.415,-2.212],[-1.507,-2.671],[0,0],[15.415,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[5.452,-4.363],[0.346,-1.388],[-3.245,-3.638],[1.17,-1.506],[3.729,3.506],[0.166,3.179],[-0.332,1.673],[0,0],[4.686,2.34],[1.771,3.146],[0,0],[-20.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[130.488,25.468],[-230.581,25.468],[-230.581,1.559],[129.819,1.559],[143.026,1.559],[147.375,1.559],[163.089,1.559],[167.939,1.559],[176.13,1.559],[180.811,1.559],[185.828,1.559],[191.346,-6.968],[203.384,-13.486],[200.375,-23.851],[199.37,-31.042],[210.906,-29.536],[215.756,-19.005],[214.918,-12.482],[213.417,-10.141],[220.603,-7.967],[228.297,0.891],[230.582,32.437],[212.302,34.889],[186.442,25.468],[180.811,25.468],[172.117,25.468],[163.089,25.468],[147.375,25.468],[143.026,25.468]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0,0.129,0.251,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":1,"ml":10,"nm":"S"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[940.896,132.7]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-15.848,-0.223],[0,0],[1.772,3.145],[4.685,2.341],[0,0],[-0.331,1.672],[0.166,3.178],[3.728,3.505],[1.17,-1.507],[-3.245,-3.639],[0.346,-1.388],[5.453,-4.363],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[2.612,4.399],[13.259,-1.376],[0,0],[-1.506,-2.672],[-4.415,-2.212],[0,0],[0.337,-1.672],[-0.166,-3.174],[-5.685,-5.353],[-1.146,1.477],[4.178,4.68],[-0.668,2.676],[-4.178,3.344],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-105.281,25.025],[-105.281,25.357],[61.655,25.357],[88.852,35],[105.19,33.233],[103.509,0.78],[95.816,-8.079],[88.63,-10.253],[90.131,-12.593],[90.97,-19.116],[86.119,-29.647],[74.584,-31.153],[75.588,-23.962],[78.596,-13.597],[66.559,-7.079],[61.04,1.448],[56.024,1.448],[-105.281,1.95],[-105.281,6.801],[-105.281,16.83]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.322,0.812,0.518,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1065.683,132.812]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":1228,"st":0},{"ind":61,"ty":4,"nm":"d","parent":17,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-50,-79,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[6.975,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[36.476,-28.415],[36.476,15.542],[22.169,25.873],[-36.477,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1181.357,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.261,2.367],[0,0],[0,1.835],[0,0],[-7.008,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[-2.482,-0.905],[0,0],[-0.859,-1.611],[0,0],[0,-7.67],[0,0],[4.167,1.613],[0,0],[0,0]],"v":[[5.927,107.801],[-56.873,84.916],[-62.685,79.836],[-77.571,51.901],[-78.88,46.65],[-78.88,-94.83],[-64.377,-105.089],[71.954,-52.33],[78.88,-42.073],[78.88,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1138.954,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-9.733],[0,0],[15.128,3.981],[0,0],[0,0],[0,0],[0,0],[0,0],[-3.939,1.871],[-2.779,-1.312]],"o":[[0,0],[0,0],[0,0],[-15.127,-3.982],[0,0],[0,0],[0,0],[0,0],[0.569,-4.194],[2.204,-0.976],[0,0]],"v":[[72.613,-65.482],[79.095,-53.095],[79.095,105.725],[63.104,115.458],[-59.646,69.891],[-64.832,62.37],[-79.095,35.384],[-78.23,28.306],[-78.23,-108.837],[-71.748,-118.127],[-64.4,-118.127]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1138.305,705.556]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":38,"op":64,"st":0},{"ind":62,"ty":4,"nm":"d","parent":18,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-126,-119,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-6.669,4.373]],"o":[[-6.669,4.372],[0,0]],"v":[[-72.026,-117.132],[78.696,112.758]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1135.266,706.895]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[4.327,-4.699],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[10.983,-32.695],[10.983,-1.622],[7.562,15.365],[-11.889,32.695]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1225.851,786.958]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-12.298,-4.493],[-23.143,-9.041],[-22.805,-9.215],[0,-5],[0.172,-39.102]],"o":[[27.744,-16.857],[6.487,2.481],[21.744,8.04],[4,2],[0,39],[0,0]],"v":[[-86.882,-73.822],[-48.024,-85.594],[13.882,-61.423],[78.882,-37.423],[86.882,-26.423],[86.71,90.678]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1150.122,663.585]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-9.733],[0,0],[11.475,-10.224],[0,0],[0,0],[0,0],[0,0],[0,0],[-3.939,1.872],[-2.778,-1.312]],"o":[[0,0],[0,9.733],[-1.866,2.288],[-1.674,0.062],[0,0],[0,0],[0,0],[0,0],[9.127,-5.528],[2.204,-0.975],[0,0]],"v":[[80.353,-70.308],[86.836,-57.921],[86.836,100.899],[63.886,122.505],[57.327,116.613],[33.941,85.318],[-37.671,-21.888],[-85.506,-101.703],[-86.836,-107.385],[-65.404,-119.789],[-54.012,-121.255]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1150.076,697.148]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":38,"op":64,"st":0},{"ind":63,"ty":4,"nm":"b","parent":19,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[123,-278,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-19.518,6.981]],"o":[[19.975,-7.545],[0,0]],"v":[[-30.247,10.763],[30.246,-10.763]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[930.276,796.943]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-22,8],[-7,12],[-0.32,47.452]],"o":[[21.483,-8.019],[9,-10],[0,-47],[0,0]],"v":[[-43.401,99.735],[22.082,76.716],[43.082,41.716],[43.401,-99.736]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.924,686.444]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.14,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[-37.335,-28.415],[-37.335,15.542],[-22.69,25.873],[37.336,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[936.187,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.291,2.367],[0,0],[0,1.835],[0,0],[7.173,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[2.54,-0.905],[0,0],[0.879,-1.611],[0,0],[0,-7.67],[0,0],[-4.266,1.613],[0,0],[0,0]],"v":[[-6.066,107.801],[58.212,84.916],[64.161,79.836],[79.398,51.901],[80.737,46.65],[80.737,-94.83],[65.893,-105.089],[-73.649,-52.33],[-80.737,-42.073],[-80.737,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[979.588,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.591,1.697],[-0.105,1.416],[-0.23,0.568],[0,0],[5.556,-0.154],[0,0],[0.645,-1.456],[7.506,-10.569],[0.734,-0.251],[0.643,-0.138],[4.886,-1.77],[7.05,-2.138],[14.569,-5.251],[0,0],[-0.059,-0.154],[-1.434,-3.399],[-0.458,-0.463],[-3.041,0.294],[-0.982,0.273],[-9.367,2.812],[-11.546,4.084],[-11.368,4.678],[-4.957,1.419],[-3.277,2.289],[-3.358,6.006],[-1.936,3.082]],"o":[[0.459,-1.318],[0.047,-0.639],[0,0],[-2.987,-4.684],[0,0],[0.588,0.987],[-5.307,11.976],[-0.606,0.853],[-0.462,0.291],[-5.093,1.096],[-6.928,2.511],[-14.824,4.497],[-10.106,3.643],[0,0],[0.151,2.829],[0.4,0.467],[2.125,1.496],[0.69,-0.519],[16.286,-4.514],[11.729,-3.52],[11.582,-4.096],[4.765,-1.961],[3.784,-1.082],[3.031,-4.704],[2.017,-3.608],[0.531,-1.722]],"v":[[80.298,37.236],[80.711,33.24],[81.139,31.421],[81.139,-110.782],[67.098,-118.313],[67.098,19.669],[67.167,23.374],[47.788,57.057],[45.745,58.676],[44.095,59.334],[29.153,64.741],[9.339,71.601],[-32.732,86.728],[-65.979,97.923],[-81.08,103.647],[-78.852,114.573],[-74.963,116.971],[-69.581,117.693],[-67.032,116.68],[-32.36,105.561],[2.167,93.004],[36.746,80.469],[51.195,75.15],[61.998,70.444],[72.826,51.662],[78.608,41.529]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[979.716,704.434]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-22,8],[-7,12],[-0.32,47.452]],"o":[[21.483,-8.019],[9,-10],[0,-47],[0,0]],"v":[[-43.401,99.735],[22.082,76.716],[43.082,41.716],[43.401,-99.736]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1003.924,686.444]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.948,0],[0,5.222],[4.947,0]],"o":[[0,5.222],[4.947,0],[0,-5.223],[-4.948,0]],"v":[[-8.958,0],[0,9.456],[8.958,0],[0,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1024.823,530.913]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.222],[4.948,0]],"o":[[0,5.222],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[994.409,543.632]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.223],[4.948,0]],"o":[[0,5.223],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[959.459,556.904]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[-4.947,0],[0,5.223],[4.948,0]],"o":[[0,5.223],[4.948,0],[0,-5.223],[-4.947,0]],"v":[[-8.958,0],[-0.001,9.456],[8.958,0],[-0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[922.63,571.061]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.223],[-4.948,0]],"o":[[0,5.223],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.958,0],[0,9.456],[-8.959,0],[0,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[883.81,581.236]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.223],[-4.948,0]],"o":[[0,5.223],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.959,0],[0.001,9.456],[-8.958,0],[0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[847.091,567.964]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-5.223],[4.947,0],[0,5.222],[-4.948,0]],"o":[[0,5.222],[-4.948,0],[0,-5.223],[4.947,0]],"v":[[8.959,0],[0.001,9.456],[-8.958,0],[0.001,-9.456]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[817.008,549.826]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[24.097,8.032],[-24.098,-8.032]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[874.007,510.924]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[6.025,-30.925],[-6.024,-0.402],[-2.812,30.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[872.802,510.522]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[4.82,-30.925],[24.098,8.434],[-4.016,30.925],[-24.097,-7.631]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[874.007,510.522]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-24.097,8.032],[24.097,-8.032]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[949.936,491.557]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-6.024,-30.925],[6.024,-0.402],[2.812,30.925]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[951.141,491.155]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-4.819,-30.925],[-24.097,8.434],[4.017,30.925],[24.098,-7.631]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[949.936,491.155]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.14,2.542],[0,0]],"o":[[0,0],[0,7.579],[0,0],[0,0]],"v":[[-37.335,-28.415],[-37.335,15.542],[-22.69,25.873],[37.336,4.502]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[936.187,795.678]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.291,2.367],[0,0],[0,1.835],[0,0],[7.173,-2.712],[0,0],[0,-4.56],[0,0]],"o":[[0,0],[2.54,-0.905],[0,0],[0.879,-1.611],[0,0],[0,-7.67],[0,0],[-4.266,1.613],[0,0],[0,0]],"v":[[-6.066,107.801],[58.212,84.916],[64.161,79.836],[79.398,51.901],[80.737,46.65],[80.737,-94.83],[65.893,-105.089],[-73.649,-52.33],[-80.737,-42.073],[-80.737,74.884]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[979.588,692.379]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.511,1.186],[0,0],[0.014,-5.253],[0,0],[-0.697,-1.119],[0,0],[-1.35,-0.593],[0,0],[0.024,5.187],[0,0]],"o":[[0,0],[-0.013,-2.719],[0,0],[-4.851,-2.292],[0,0],[-0.004,1.31],[0,0],[0.768,1.233],[0,0],[4.855,2.13],[0,0],[0,0]],"v":[[36.582,69.522],[36.067,-71.032],[31.943,-77.414],[-25.981,-104.779],[-36.488,-98.383],[-36.892,56.11],[-35.832,59.825],[-21.818,82.338],[-18.567,85.141],[26.552,104.94],[36.872,98.409],[36.734,69.522]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[831.343,714.552]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[6.464,0],[0,8.344],[-4.924,2.734]],"o":[[-4.668,2.091],[-15.026,0],[0,-4.172],[0,0]],"v":[[22.139,9.552],[5.069,12.895],[-22.138,-2.213],[-14.169,-12.895]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[808.179,817.41]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.261,0],[0,7.513],[-0.705,1.437]],"o":[[0.516,1.249],[0,7.513],[-10.262,0],[0,-1.614],[0,0]],"v":[[17.786,-8.448],[18.58,-4.501],[0,9.102],[-18.581,-4.501],[-17.492,-9.102]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[812.805,836.023]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-3.305],[15.026,0],[4.978,3.561]],"o":[[3.243,2.487],[0,8.344],[-8.748,0],[0,0]],"v":[[19.204,-11.979],[24.358,-3.129],[-2.849,11.979],[-24.358,6.125]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1032.871,798.861]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.261,0],[0,7.513],[-0.705,1.437]],"o":[[0.516,1.249],[0,7.513],[-10.262,0],[0,-1.614],[0,0]],"v":[[17.786,-8.448],[18.58,-4.501],[0,9.102],[-18.581,-4.501],[-17.492,-9.102]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1029.579,816.557]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-1.373],[10.262,0],[0,7.513],[-0.704,1.437]],"o":[[1.025,0.937],[0,7.513],[-10.262,0],[0,-1.615],[0,0]],"v":[[17.133,-9.102],[18.581,-4.501],[-0.001,9.102],[-18.581,-4.501],[-17.492,-9.101]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[886.686,868.317]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-2.311],[14.843,0],[0,8.613],[-1.156,1.076]],"o":[[1.554,1.973],[0,8.613],[-14.843,0],[0,-1.077],[0,0]],"v":[[24.455,-11.036],[26.875,-4.558],[0,11.036],[-26.875,-4.558],[-25.166,-9.239]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[886.64,851.548]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[883.81,845.788],[883.81,778.765]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[883.81,778.765],[883.81,630.937]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-41.838,-20.679],[0,0],[-13.667,5.067],[0,0],[45.715,17.404],[6.243,0.052]],"o":[[0,0],[-43.889,15.871],[0,0],[13.068,6.458],[0,0],[45.865,-17.004],[-5.927,-2.256],[0,0]],"v":[[-48.32,-39.792],[-53.245,-38.011],[-58.703,59.297],[-57.951,59.669],[-16.064,61.849],[54.392,35.727],[54.825,-63.452],[36.421,-66.916]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.482,494.565]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[5.964,-2.156],[0,0]],"o":[[-6.243,-0.052],[0,0],[0,0]],"v":[[42.371,-13.536],[23.911,-10.381],[-42.37,13.588]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[913.533,441.185]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-22.66,-11.2],[0,0],[-7.403,2.745],[0,0],[24.759,9.426],[0,0]],"o":[[0,0],[-23.77,8.596],[0,0],[7.078,3.498],[0,0],[24.84,-9.21],[0,0],[0,0]],"v":[[-92.612,-34.094],[-110.589,-27.593],[-113.545,25.109],[-52.348,55.356],[-29.661,56.536],[111.212,4.308],[111.446,-49.407],[85.514,-59.28]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[923.265,544.66]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-10.475,-5.177],[0,0],[-3.422,1.268],[0,0],[11.446,4.357],[0,0]],"o":[[0,0],[-10.989,3.973],[0,0],[3.272,1.617],[0,0],[11.483,-4.258],[0,0],[0,0]],"v":[[-130.762,-30.138],[-147.021,-24.258],[-148.388,0.104],[-48.788,49.332],[-38.301,49.878],[147.31,-18.937],[147.418,-43.768],[128.039,-51.146]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[925.005,580.174]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[-17.728,-9.042],[0,0],[-13.831,5.068],[0,0],[0,22.215],[0,0]],"o":[[0,0],[0,19.9],[0,0],[13.122,6.693],[0,0],[20.858,-7.643],[0,0],[0,0]],"v":[[-146.322,-121.324],[-146.322,63.906],[-117.435,111.068],[-68.026,136.271],[-25.755,138.818],[111.596,88.488],[146.322,38.778],[146.322,-143.886]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[926.833,704.772]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[4.866,2.654],[0,0],[0.884,-7.078],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[-4.866,-2.655],[0,0],[-0.885,7.078],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[36.055,-65.032],[31.631,-76.534],[-27.65,-104.849],[-36.055,-98.654],[-36.498,57.511],[-21.456,84.497],[-11.281,89.806],[25.88,105.29],[33.843,105.733],[36.94,100.423]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.02,0.482,0.843,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[831.386,713.955]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-5.428,-31.084],[-23.566,8.079],[4.305,31.084],[23.566,-7.609]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[950.288,491.314]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-23.668,-6.194],[-4.203,29.641],[23.668,8.406],[4.645,-29.641]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[873.413,510.452]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.597,-22.99],[0,0],[0,-6.193],[-8.721,-4.298],[0,0],[-9.291,3.539],[0,0],[0.442,4.424],[1.327,0.885],[0,0],[26.544,10.175],[0,0],[16.466,16.466],[18.58,-4.866],[0,0],[4.494,-21.791],[0,0],[0,0]],"o":[[0,0],[0,0],[0,6.194],[0,0],[0,0],[9.29,-3.54],[0,0],[-0.442,-4.423],[-1.327,-0.885],[0,0],[-15.484,-7.963],[0,0],[-17.696,-17.696],[-18.581,4.866],[0,0],[-3.535,18.475],[0,0],[0,0]],"v":[[-131.159,21.003],[-149.094,27.428],[-156.159,38.952],[-144.892,53.023],[-49.998,100.866],[-32.744,99.539],[151.734,30.083],[155.716,19.907],[150.407,9.29],[127.403,-0.443],[106.61,-34.507],[83.164,-43.654],[69.449,-83.613],[13.266,-98.212],[-63.27,-70.784],[-91.81,-38.299],[-93.611,-18.468],[-116.036,-10.882]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[925.402,529.033]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.205,-0.719],[6.972,-12.532],[1.409,-0.652],[12.518,-4.674],[14.678,-4.72],[6.918,-2.946],[6.504,-2.265],[0.872,7.84],[0,1.586],[0,0],[0,0.419],[0,0],[-0.718,1.473],[-0.111,0.198],[-4.232,1.296],[-1.455,0.565],[-5.873,2.236],[-17.537,6.674],[-10.891,4.659],[-9.839,1.97],[-2.72,-0.142],[-0.908,-1.043],[-0.64,-3.923],[0,-1.229],[0,0]],"o":[[-5.824,11.718],[-0.281,1.1],[-12.146,5.623],[-14.442,5.394],[-7.146,2.299],[-6.327,2.695],[-7.126,2.482],[-0.916,-0.805],[0,0],[-0.079,-0.364],[0,0],[-0.492,-1.211],[0.101,-0.206],[0.573,-4.286],[1.513,-0.697],[5.864,-2.276],[17.53,-6.674],[11.637,-4.427],[4.004,-1.713],[2.397,-1.257],[1.509,0.079],[3.536,0.796],[0.59,0.76],[0,0],[0.072,0.615]],"v":[[133.166,36.389],[116.586,67.576],[113.183,71.41],[75.613,84.364],[31.962,99.644],[10.648,106.859],[-8.37,114.909],[-26.604,108.326],[-28.129,104.741],[-28.129,0.271],[-28.252,-0.902],[-28.252,-52.668],[-28.065,-56.774],[-27.738,-57.372],[-18.365,-64.953],[-13.865,-66.824],[3.102,-73.657],[56.379,-93.436],[89.317,-106.318],[114.032,-114.819],[121.941,-117.038],[125.694,-115.271],[132.388,-108.518],[133.345,-105.537],[133.345,34.385]],"c":true}},"nm":"P"},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-11.281,-8.627],[0,0],[0,0],[-25.87,11.613],[0,0],[0,38.709],[0,0]],"o":[[0,0],[0,0],[0,0],[4.7,7.852],[0,0],[0,0],[68.939,-24.365],[0,0],[0,-34.507],[0,0]],"v":[[-14.599,-148.147],[-146.654,-121.604],[-146.654,68.184],[-132.055,100.036],[-117.01,111.318],[-66.449,138.087],[-18.58,136.535],[116.48,86.635],[145.991,37.001],[146.654,-143.502]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.004,0.502,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[927.164,704.388]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-7.806],[10.079,0],[0,6.506],[-10.078,0]],"o":[[0,6.505],[-10.078,0],[0,-6.505],[10.079,0]],"v":[[18.816,1.184],[0.567,12.964],[-18.815,0.051],[0.567,-12.964]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1029.455,812.364]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-8.85],[14.455,0],[0,8.85],[-14.454,0]],"o":[[0,8.85],[-14.454,0],[0,-8.85],[14.455,0]],"v":[[26.67,0.706],[-0.498,15.318],[-26.67,0.706],[-0.498,-15.318]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1030.559,795.521]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-7.327],[10.262,0],[0,7.327],[-10.261,0]],"o":[[0,7.327],[-10.261,0],[0,-7.327],[10.262,0]],"v":[[18.581,0],[-0.001,13.266],[-18.581,0],[-0.001,-13.266]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[886.685,864.153]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-8.85],[14.763,0],[0,8.85],[-14.764,0]],"o":[[0,8.85],[-14.764,0],[0,-8.85],[14.763,0]],"v":[[26.733,0],[0,16.023],[-26.732,0],[0,-16.023]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[886.496,846.991]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[29.862,0.995],[0.664,-17.585],[0,0],[0,0],[-16.59,0.664],[1.991,5.309]],"o":[[0,0],[1.041,5.758],[0,0],[0,0],[16.59,-0.663],[0,0]],"v":[[-1.659,-17.997],[-28.203,-5.64],[-18.912,4.977],[-20.24,11.281],[-0.332,22.562],[15.788,5.115]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[814.354,822.01]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":64,"ty":4,"nm":"c","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[95,-200,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,766.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[948.066,766.516],[948.066,776.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[891.544,766.516],[891.544,776.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,779.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,766.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[919.805,771.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[910.805,778.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[939.066,778.516],[939.066,788.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[882.544,778.516],[882.544,788.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[910.805,791.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[910.805,778.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[910.805,783.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,791.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[948.066,791.516],[948.066,801.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[891.544,791.516],[891.544,801.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,804.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[919.805,791.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[919.805,796.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[911.805,804.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[940.066,804.516],[940.066,814.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[883.544,804.516],[883.544,814.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[911.805,817.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[911.805,804.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[911.805,809.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":65,"ty":4,"nm":"c","parent":21,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[40,-167,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,733.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1000.066,733.516],[1000.066,743.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[943.544,733.516],[943.544,743.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,746.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,733.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[971.805,738.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[962.805,745.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[991.066,745.516],[991.066,755.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[934.544,745.516],[934.544,755.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[962.805,758.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[962.805,745.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[962.805,750.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,758.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1000.066,758.516],[1000.066,768.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[943.544,758.516],[943.544,768.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,771.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[971.805,758.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[971.805,763.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.805,771.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[992.066,771.516],[992.066,781.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[935.544,771.516],[935.544,781.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.242,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.805,784.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[963.805,771.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[963.805,776.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":66,"ty":4,"nm":"c","parent":22,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-8,-171,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,739.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[984.231,739.271],[984.231,749.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1039.776,739.271],[1039.776,749.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.007,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,752.302]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.773,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,739.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.772,-5],[-27.355,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1012.003,744.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.848,751.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[993.075,751.271],[993.075,761.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1048.62,751.271],[1048.62,761.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.006,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.848,764.302]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.772,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.848,751.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.772,-5],[-27.355,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1020.848,756.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,764.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[984.231,764.271],[984.231,774.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1039.776,764.271],[1039.776,774.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.007,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,777.302]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.773,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1012.003,764.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.772,-5],[-27.355,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1012.003,769.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.865,777.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[992.092,777.271],[992.092,787.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1047.638,777.271],[1047.638,787.271]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.007,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.865,790.302]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.772,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.865,777.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.772,-5],[-27.355,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1019.865,782.271]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":67,"ty":4,"nm":"g","parent":23,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-6,-120,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-15.004,-14.219],[15.004,14.22]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1046.58,682.649]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[25.105,-6.669],[-25.105,6.669]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1006.471,675.098]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.997,19.024],[6.997,-19.025]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[974.369,700.792]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-30.827,-22.653],[30.828,22.653]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[998.199,742.469]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[16.279,-34.127],[-16.279,34.127]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1045.305,730.996]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-5.782,31.611],[5.782,-31.61]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1034.809,733.512]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.865,28.39],[-6.865,-28.39]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1022.162,736.733]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-19.055,-25.521],[19.054,25.521]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1009.972,739.602]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-16.966,-13.288],[16.965,13.288]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[998.332,695.055]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8.14,-19.957],[-8.14,19.956]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1023.436,688.386]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-47.107,11.473],[47.106,-11.474]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1014.478,708.343]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-4.898,-29.025],[-16.094,34.056],[16.094,-34.057],[5.045,-31.413]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1045.49,730.926]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-19.239,-22.581],[19.239,28.32],[5.141,-28.32],[-10.846,-24.625]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1010.156,736.662]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-23.143,20.026],[2.151,13.586],[23.144,8.552],[-6.751,-20.026]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1038.44,688.316]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-24.036,19.099],[-0.343,13.216],[24.036,7.478],[-9.895,-19.099]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[991.26,700.865]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[6.655,6.275],[2.997,2.884],[4.085,-1.028],[5.638,-1.449],[4.943,-1.792],[2.279,-0.386],[1.279,-3.395],[3.747,-9.154],[-4.642,-3.606],[-8.639,-5.896],[-7.678,-5.761],[-0.402,0.474],[-0.027,0.032],[-0.025,0.098],[-2.556,3.838],[-0.975,1.827],[-0.109,0.277],[-3.204,6.475],[-3.35,7.425],[-0.974,1.941]],"o":[[-3.667,-3.458],[-3.879,1.541],[-5.645,1.42],[-5.09,1.309],[-2.298,0.833],[-1.237,3.949],[-3.488,9.255],[4.793,3.363],[8.254,6.414],[7.927,5.409],[0.203,-0.504],[0.027,-0.032],[0.02,-0.096],[1.174,-4.461],[0.792,-1.977],[0.107,-0.279],[2.647,-6.729],[3.613,-7.304],[0.893,-1.98],[-6.967,-5.903]],"v":[[27.21,-38.784],[17.172,-48.346],[5.112,-45.241],[-11.803,-40.883],[-26.907,-36.448],[-33.713,-34.506],[-37.42,-23.24],[-47.292,3.328],[-33.803,13.096],[-8.78,31.964],[14.879,48.346],[15.777,46.872],[15.855,46.775],[15.902,46.49],[22.04,34.117],[24.631,28.414],[24.953,27.578],[34.223,8.013],[44.479,-14.135],[47.292,-20.01]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.004,0.502,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1014.516,716.636]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":68,"ty":4,"nm":"g","parent":24,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[78,-134,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-5.892,-19.814],[5.892,19.814]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[970.626,718.181]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[25.078,6.767],[-25.078,-6.768]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[939.656,691.599]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-15.567,12.983],[15.568,-12.983]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[899.01,697.815]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-15.384,-35.026],[15.385,35.026]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[898.827,745.824]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[31.153,-21.427],[-31.153,21.428]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[945.365,759.422]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-20.804,24.492],[20.803,-24.492]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[935.015,756.357]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-8.239,28.022],[8.239,-28.022]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[922.45,752.828]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.753,-31.627],[3.753,31.627]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[910.458,749.223]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-8.057,-19.987],[8.056,19.987]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[922.634,704.819]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[17.022,-13.219],[-17.022,13.22]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[947.712,711.586]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46.537,-13.598],[46.537,13.598]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[929.98,724.397]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[10.259,-24.524],[-30.958,24.524],[30.958,-18.394],[20.065,-21.624]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[945.559,756.389]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-11.992,-31.659],[-4.096,31.659],[11.992,-24.447],[-3.702,-29.235]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[918.697,749.254]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-22.914,6.658],[2.215,13.717],[22.914,19.847],[11.298,-19.847]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[953.604,718.148]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-23.724,6.034],[-0.261,12.776],[23.724,19.987],[7.612,-19.987]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.459,0.855,0.875,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[906.965,704.819]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.629,8.761],[1.155,3.995],[4.052,1.151],[5.608,1.562],[5.176,0.918],[2.167,0.805],[2.805,-2.302],[7.821,-6.057],[-2.218,-5.443],[-4.538,-9.424],[-3.772,-8.827],[-0.585,0.211],[-0.039,0.015],[-0.071,0.072],[-4.131,2.048],[-1.757,1.095],[-0.233,0.185],[-6.01,4.007],[-6.612,4.759],[-1.813,1.194]],"o":[[-1.449,-4.828],[-4.13,-0.604],[-5.599,-1.59],[-5.063,-1.41],[-2.408,-0.427],[-3.044,2.803],[-7.645,6.274],[2.472,5.308],[3.945,9.68],[4.163,8.646],[0.428,-0.335],[0.04,-0.014],[0.066,-0.073],[3.246,-3.278],[1.674,-1.317],[0.232,-0.189],[5.655,-4.507],[6.78,-4.522],[1.763,-1.269],[-3.085,-8.595]],"v":[[38.781,-21.288],[34.864,-34.587],[22.866,-37.924],[6.036,-42.599],[-9.262,-46.305],[-16.129,-48.024],[-24.97,-40.116],[-46.796,-22.036],[-39.992,-6.835],[-27.743,22.012],[-15.436,48.025],[-13.922,47.196],[-13.805,47.15],[-13.622,46.927],[-2.124,39.276],[2.971,35.63],[3.668,35.068],[21.473,22.752],[41.424,8.691],[46.796,5.008]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.004,0.502,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[930.037,732.889]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":69,"ty":4,"nm":"c","parent":25,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[54,-87,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,655.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[923.042,655.305],[923.042,665.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[978.588,655.305],[978.588,665.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.006,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,668.336]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.773,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,655.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.773,-5],[-27.356,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[950.815,660.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[959.66,667.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[931.887,667.305],[931.887,677.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[987.432,667.305],[987.432,677.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.007,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[959.66,680.336]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.773,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[959.66,667.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.773,-5],[-27.356,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[959.66,672.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,680.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[923.042,680.305],[923.042,690.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[978.588,680.305],[978.588,690.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.006,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,693.336]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.773,0],[0,6.572],[27.772,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[950.815,680.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.773,-5],[-27.356,6.129],[-1.07,11.572],[27.72,5.39],[27.772,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[950.815,685.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[-7.108,0],[0,1.682],[7.108,0]],"o":[[0,1.682],[7.108,0],[0,-1.682],[-7.108,0]],"v":[[-12.871,0],[0,3.046],[12.871,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[958.677,693.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[930.904,693.305],[930.904,703.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[986.45,693.305],[986.45,703.305]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[15.338,0],[0,3.63],[-0.007,0.06]],"o":[[0.055,0.168],[0,3.63],[-15.338,0],[0,-0.06],[0,0]],"v":[[27.681,-3.542],[27.773,-3.031],[0,3.542],[-27.773,-3.031],[-27.754,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[958.677,706.336]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[-15.339,0],[0,3.63],[15.338,0]],"o":[[0,3.63],[15.338,0],[0,-3.63],[-15.339,0]],"v":[[-27.772,0],[0,6.572],[27.773,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[958.677,693.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[-0.417,-3.041],[-7.296,0],[-4.559,6.182],[0,2.251],[9.904,0]],"o":[[0,1.713],[4.422,4.02],[6.479,0],[0.052,-3.818],[0,-5.043],[-9.905,0]],"v":[[-27.772,-5],[-27.355,6.129],[-1.07,11.572],[27.721,5.39],[27.773,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[958.677,698.305]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":70,"ty":4,"nm":"c","parent":26,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[-16,-94,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,662.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1057.066,662.516],[1057.066,672.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1000.544,662.516],[1000.544,672.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.241,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,675.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,662.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1028.805,667.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.805,674.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1048.066,674.516],[1048.066,684.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[991.544,674.516],[991.544,684.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.241,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.805,687.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1019.805,674.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1019.805,679.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,687.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1057.066,687.516],[1057.066,697.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1000.544,687.516],[1000.544,697.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.241,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,700.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1028.805,687.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1028.805,692.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-1.682],[7.233,0],[0,1.682],[-7.234,0]],"o":[[0,1.682],[-7.234,0],[0,-1.682],[7.233,0]],"v":[[13.097,0],[0,3.046],[-13.097,0],[0,-3.046]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.805,700.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1049.066,700.516],[1049.066,710.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[992.544,700.516],[992.544,710.516]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-0.172],[-15.608,0],[0,3.63],[0.007,0.06]],"o":[[-0.056,0.168],[0,3.63],[15.608,0],[0,-0.06],[0,0]],"v":[[-28.167,-3.542],[-28.26,-3.031],[0,3.542],[28.26,-3.031],[28.241,-3.21]],"c":false}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.805,713.547]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-3.63],[15.608,0],[0,3.63],[-15.608,0]],"o":[[0,3.63],[-15.608,0],[0,-3.63],[15.608,0]],"v":[[28.261,0],[0,6.572],[-28.261,0],[0,-6.572]],"c":true}},"nm":"P"},{"ty":"st","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":2,"lj":2,"nm":"S"},{"ty":"tr","p":{"a":0,"k":[1020.805,700.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-4.941],[0.424,-3.041],[7.424,0],[4.639,6.182],[0,2.251],[-10.078,0]],"o":[[0,1.713],[-4.5,4.02],[-6.592,0],[-0.054,-3.818],[0,-5.043],[10.079,0]],"v":[[28.261,-5],[27.837,6.129],[1.088,11.572],[-28.207,5.39],[-28.261,-4.646],[0,-11.572]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.894,0.737,0.027,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[1020.805,705.516]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0},{"ind":71,"ty":4,"nm":"b","parent":27,"sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[30,-114,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[100,100,100],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.599,-114.088],[77.845,-30.921],[3.198,101.826],[-101.123,46.915]],"o":[[5.331,115.762],[-117.65,39.451],[0,-126.35],[98.798,-37.851]],"v":[[95.429,-23.191],[9.426,103.692],[-85.299,30.121],[9.426,-105.292]],"c":true}},"nm":"P"},{"ty":"fl","c":{"a":0,"k":[0.043,0.106,0.204,1]},"o":{"a":0,"k":100},"r":1,"nm":"F"},{"ty":"tr","p":{"a":0,"k":[973.054,702.158]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"T"}],"nm":"G"}],"ip":0,"op":64,"st":0}]}],"layers":[{"ind":1,"ty":0,"nm":"E","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[333.5,110,0],"l":2},"a":{"a":0,"k":[960,540,0],"l":2},"s":{"a":0,"k":[73,73,100],"l":2}},"ao":0,"w":1920,"h":1080,"ip":0,"op":64,"st":0}],"markers":[]} \ No newline at end of file diff --git a/config/electronBuilder.config.js b/config/electronBuilder.config.js index da87c93ee367..a5478dbd8f78 100644 --- a/config/electronBuilder.config.js +++ b/config/electronBuilder.config.js @@ -21,6 +21,24 @@ const macIcon = { adhoc: './desktop/icon-adhoc.png', }; +const appIds = { + production: 'com.expensifyreactnative.chat', + staging: 'com.expensifyreactnative.dev.chat', + adhoc: 'com.expensifyreactnative.adhoc.chat', +}; + +const productNames = { + production: 'New Expensify', + staging: 'New Expensify Dev', + adhoc: 'New Expensify AdHoc', +}; + +const artifactNames = { + production: 'NewExpensify.dmg', + staging: 'NewExpensifyDev.dmg', + adhoc: 'NewExpensifyAdHoc.dmg', +}; + const isCorrectElectronEnv = ['production', 'staging', 'adhoc'].includes(process.env.ELECTRON_ENV); if (!isCorrectElectronEnv) { @@ -32,8 +50,8 @@ if (!isCorrectElectronEnv) { * It can be used to create local builds of the same, by omitting the `--publish` flag */ module.exports = { - appId: 'com.expensifyreactnative.chat', - productName: 'New Expensify', + appId: appIds[process.env.ELECTRON_ENV], + productName: productNames[process.env.ELECTRON_ENV], extraMetadata: { version, }, @@ -46,8 +64,8 @@ module.exports = { type: 'distribution', }, dmg: { - title: 'New Expensify', - artifactName: 'NewExpensify.dmg', + title: productNames[process.env.ELECTRON_ENV], + artifactName: artifactNames[process.env.ELECTRON_ENV], internetEnabled: true, }, publish: [ @@ -65,7 +83,7 @@ module.exports = { output: 'desktop-build', }, protocols: { - name: 'New Expensify', + name: productNames[process.env.ELECTRON_ENV], schemes: ['new-expensify'], }, }; diff --git a/contributingGuides/PROPTYPES_CONVERSION_TABLE.md b/contributingGuides/PROPTYPES_CONVERSION_TABLE.md index e7584f82a351..7e1c1dda4262 100644 --- a/contributingGuides/PROPTYPES_CONVERSION_TABLE.md +++ b/contributingGuides/PROPTYPES_CONVERSION_TABLE.md @@ -1,5 +1,7 @@ # Expensify PropTypes Conversion Table +This is a reference to help you convert PropTypes to TypeScript types. + ## Table of Contents - [Important Considerations](#important-considerations) diff --git a/desktop/main.js b/desktop/main.js index b19bef060ba9..5e184d529afd 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -12,7 +12,7 @@ const CONST = require('../src/CONST').default; const Localize = require('../src/libs/Localize'); const port = process.env.PORT || 8082; -const {DESKTOP_SHORTCUT_ACCELERATOR} = CONST; +const {DESKTOP_SHORTCUT_ACCELERATOR, LOCALES} = CONST; app.setName('New Expensify'); @@ -36,25 +36,40 @@ function pasteAsPlainText(browserWindow) { browserWindow.webContents.insertText(text); } -// Initialize the right click menu -// See https://github.com/sindresorhus/electron-context-menu -// Add the Paste and Match Style command to the context menu -contextMenu({ - append: (defaultActions, parameters, browserWindow) => [ - new MenuItem({ - // Only enable the menu item for Editable context which supports paste - visible: parameters.isEditable && parameters.editFlags.canPaste, - role: 'pasteAndMatchStyle', - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, - }), - new MenuItem({ - label: Localize.translate(CONST.LOCALES.DEFAULT, 'desktopApplicationMenu.pasteAsPlainText'), - visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, - click: () => pasteAsPlainText(browserWindow), - }), - ], -}); +/** + * Initialize the right-click menu + * See https://github.com/sindresorhus/electron-context-menu + * + * @param {String} preferredLocale - The current user language to be used for translating menu labels. + * @returns {Function} A dispose function to clean up the created context menu. + */ + +function createContextMenu(preferredLocale = LOCALES.DEFAULT) { + return contextMenu({ + labels: { + cut: Localize.translate(preferredLocale, 'desktopApplicationMenu.cut'), + paste: Localize.translate(preferredLocale, 'desktopApplicationMenu.paste'), + copy: Localize.translate(preferredLocale, 'desktopApplicationMenu.copy'), + }, + append: (defaultActions, parameters, browserWindow) => [ + new MenuItem({ + // Only enable the menu item for Editable context which supports paste + visible: parameters.isEditable && parameters.editFlags.canPaste, + role: 'pasteAndMatchStyle', + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAndMatchStyle'), + }), + new MenuItem({ + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAsPlainText'), + visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, + click: () => pasteAsPlainText(browserWindow), + }), + ], + }); +} + +let disposeContextMenu = createContextMenu(); // Send all autoUpdater logs to a log file: ~/Library/Logs/new.expensify.desktop/main.log // See https://www.npmjs.com/package/electron-log @@ -522,6 +537,8 @@ const mainWindow = () => { ipcMain.on(ELECTRON_EVENTS.LOCALE_UPDATED, (event, updatedLocale) => { Menu.setApplicationMenu(Menu.buildFromTemplate(localizeMenuItems(initialMenuTemplate, updatedLocale))); + disposeContextMenu(); + disposeContextMenu = createContextMenu(updatedLocale); }); ipcMain.on(ELECTRON_EVENTS.REQUEST_VISIBILITY, (event) => { diff --git a/docs/articles/other/Card-Rev-Share-for-Approved-Partners.md b/docs/articles/other/Card-Revenue-Share-for-ExpensifyApproved!-Partners.md similarity index 100% rename from docs/articles/other/Card-Rev-Share-for-Approved-Partners.md rename to docs/articles/other/Card-Revenue-Share-for-ExpensifyApproved!-Partners.md diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index d87226269a8b..64ed3fda8b02 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 02BE6CF80ED1BD2445267F92 /* Pods-NewExpensify.release development.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release development.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release development.xcconfig"; sourceTree = ""; }; 0B09CE5BDAF34DD3573AB4E2 /* Pods-NewExpensify.debug adhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug adhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug adhoc.xcconfig"; sourceTree = ""; }; + 0B627F2A465153FFA6E3A4E0 /* 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 = ""; }; 0CDA8E33287DD650004ECBEC /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = NewExpensify/AppDelegate.mm; sourceTree = ""; }; 0CDA8E36287DD6A0004ECBEC /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NewExpensify/Images.xcassets; sourceTree = ""; }; 0E27AA27706D894246E7946D /* Pods-NewExpensify.debug production.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug production.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug production.xcconfig"; sourceTree = ""; }; @@ -64,38 +65,49 @@ 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 = ""; }; 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 = ""; }; 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 = ""; }; 3D393D7ABC1092F1DE91397F /* Pods-NewExpensify-NewExpensifyTests.debug staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug staging.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug staging.xcconfig"; sourceTree = ""; }; 432FF5842B766535509FC547 /* Pods-NewExpensify-NewExpensifyTests.debug adhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug adhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug adhoc.xcconfig"; sourceTree = ""; }; 44BF435285B94E5B95F90994 /* ExpensifyNewKansas-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-Medium.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-Medium.otf"; sourceTree = ""; }; + 47D5DF3C6779D41BE70CD031 /* 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 = ""; }; + 4E8BF7B08BA3181991BFCF4B /* 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 = ""; }; 52796131E6554494B2DDB056 /* ExpensifyNeue-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Bold.otf"; path = "../assets/fonts/native/ExpensifyNeue-Bold.otf"; sourceTree = ""; }; + 57DBBEDB9692E096D4BA0141 /* 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 = ""; }; 6B5211DB0EEB46E12DF4AD2D /* Pods-NewExpensify-NewExpensifyTests.release adhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release adhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release adhoc.xcconfig"; sourceTree = ""; }; 6BE16DA6EFF88513DB1CD47B /* Pods-NewExpensify-NewExpensifyTests.release staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release staging.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release staging.xcconfig"; sourceTree = ""; }; + 6F6A514B4DF07A60EC8355BA /* 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 = ""; }; 6FB387B20AE4E6E98858B6AA /* libPods-NewExpensify-NewExpensifyTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify-NewExpensifyTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; + 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 = ""; }; 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 = ""; }; AEFE6CD54912D427D19133C7 /* libPods-NewExpensify.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; + 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 = ""; }; 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 = ""; }; 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 = ""; }; 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; }; F0C450E92705020500FD2970 /* colors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = colors.json; path = ../colors.json; sourceTree = ""; }; + F15A36A3262EEC3B0CAB8EDF /* Pods-NewExpensify-NewExpensifyTests.debugproduction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debugproduction.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debugproduction.xcconfig"; 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 = ""; }; /* End PBXFileReference section */ @@ -239,6 +251,18 @@ 6B5211DB0EEB46E12DF4AD2D /* Pods-NewExpensify-NewExpensifyTests.release adhoc.xcconfig */, 6BE16DA6EFF88513DB1CD47B /* Pods-NewExpensify-NewExpensifyTests.release staging.xcconfig */, 96552D489D9F09B6A5ABD81B /* Pods-NewExpensify-NewExpensifyTests.release production.xcconfig */, + 0B627F2A465153FFA6E3A4E0 /* Pods-NewExpensify.debugdevelopment.xcconfig */, + 6F6A514B4DF07A60EC8355BA /* Pods-NewExpensify.debugadhoc.xcconfig */, + CE2F84BEE9A6DCC228AF7E42 /* Pods-NewExpensify.debugproduction.xcconfig */, + 30FFBD291B71222A393D9CC9 /* Pods-NewExpensify.releasedevelopment.xcconfig */, + BD8828A882E2D6B51362AAC3 /* Pods-NewExpensify.releaseadhoc.xcconfig */, + 47D5DF3C6779D41BE70CD031 /* Pods-NewExpensify.releaseproduction.xcconfig */, + 8709DF3C8D91F0FC1581CDD7 /* Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig */, + 25A4587E168FD67CF890B448 /* Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig */, + F15A36A3262EEC3B0CAB8EDF /* Pods-NewExpensify-NewExpensifyTests.debugproduction.xcconfig */, + 4E8BF7B08BA3181991BFCF4B /* Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig */, + E2C8555C607612465A7473F8 /* Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig */, + 57DBBEDB9692E096D4BA0141 /* Pods-NewExpensify-NewExpensifyTests.releaseproduction.xcconfig */, ); path = Pods; sourceTree = ""; @@ -641,9 +665,9 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 00E356F61AD99517003FC87E /* Debug Development */ = { + 00E356F61AD99517003FC87E /* DebugDevelopment */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E2F1036F70CBFE39E9352674 /* Pods-NewExpensify-NewExpensifyTests.debug development.xcconfig */; + baseConfigurationReference = 8709DF3C8D91F0FC1581CDD7 /* Pods-NewExpensify-NewExpensifyTests.debugdevelopment.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -664,11 +688,11 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Debug Development"; + name = DebugDevelopment; }; - 00E356F71AD99517003FC87E /* Release Development */ = { + 00E356F71AD99517003FC87E /* ReleaseDevelopment */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BD6E1BA27D6ABE0AC9D70586 /* Pods-NewExpensify-NewExpensifyTests.release development.xcconfig */; + baseConfigurationReference = 4E8BF7B08BA3181991BFCF4B /* Pods-NewExpensify-NewExpensifyTests.releasedevelopment.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -687,11 +711,11 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Release Development"; + name = ReleaseDevelopment; }; - 13B07F941A680F5B00A75B9A /* Debug Development */ = { + 13B07F941A680F5B00A75B9A /* DebugDevelopment */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CECC4CBB97A55705A33BEA9E /* Pods-NewExpensify.debug development.xcconfig */; + baseConfigurationReference = 0B627F2A465153FFA6E3A4E0 /* Pods-NewExpensify.debugdevelopment.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -719,11 +743,11 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Debug Development"; + name = DebugDevelopment; }; - 13B07F951A680F5B00A75B9A /* Release Development */ = { + 13B07F951A680F5B00A75B9A /* ReleaseDevelopment */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 02BE6CF80ED1BD2445267F92 /* Pods-NewExpensify.release development.xcconfig */; + baseConfigurationReference = 30FFBD291B71222A393D9CC9 /* Pods-NewExpensify.releasedevelopment.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDev; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -749,9 +773,9 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Release Development"; + name = ReleaseDevelopment; }; - 83CBBA201A601CBA00E9B192 /* Debug Development */ = { + 83CBBA201A601CBA00E9B192 /* DebugDevelopment */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -814,9 +838,9 @@ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; - name = "Debug Development"; + name = DebugDevelopment; }; - 83CBBA211A601CBA00E9B192 /* Release Development */ = { + 83CBBA211A601CBA00E9B192 /* ReleaseDevelopment */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -873,9 +897,9 @@ SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; - name = "Release Development"; + name = ReleaseDevelopment; }; - CF9AF93E29EE9276001FA527 /* Debug Production */ = { + CF9AF93E29EE9276001FA527 /* DebugProduction */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -938,11 +962,11 @@ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; - name = "Debug Production"; + name = DebugProduction; }; - CF9AF93F29EE9276001FA527 /* Debug Production */ = { + CF9AF93F29EE9276001FA527 /* DebugProduction */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0E27AA27706D894246E7946D /* Pods-NewExpensify.debug production.xcconfig */; + baseConfigurationReference = CE2F84BEE9A6DCC228AF7E42 /* Pods-NewExpensify.debugproduction.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -970,11 +994,11 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Debug Production"; + name = DebugProduction; }; - CF9AF94029EE9276001FA527 /* Debug Production */ = { + CF9AF94029EE9276001FA527 /* DebugProduction */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DB76E0D5C670190A0997C71E /* Pods-NewExpensify-NewExpensifyTests.debug production.xcconfig */; + baseConfigurationReference = F15A36A3262EEC3B0CAB8EDF /* Pods-NewExpensify-NewExpensifyTests.debugproduction.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -995,9 +1019,9 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Debug Production"; + name = DebugProduction; }; - CF9AF94429EE927A001FA527 /* Debug AdHoc */ = { + CF9AF94429EE927A001FA527 /* DebugAdHoc */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -1060,11 +1084,11 @@ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; - name = "Debug AdHoc"; + name = DebugAdHoc; }; - CF9AF94529EE927A001FA527 /* Debug AdHoc */ = { + CF9AF94529EE927A001FA527 /* DebugAdHoc */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0B09CE5BDAF34DD3573AB4E2 /* Pods-NewExpensify.debug adhoc.xcconfig */; + baseConfigurationReference = 6F6A514B4DF07A60EC8355BA /* Pods-NewExpensify.debugadhoc.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIconAdHoc; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -1092,11 +1116,11 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Debug AdHoc"; + name = DebugAdHoc; }; - CF9AF94629EE927A001FA527 /* Debug AdHoc */ = { + CF9AF94629EE927A001FA527 /* DebugAdHoc */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 432FF5842B766535509FC547 /* Pods-NewExpensify-NewExpensifyTests.debug adhoc.xcconfig */; + baseConfigurationReference = 25A4587E168FD67CF890B448 /* Pods-NewExpensify-NewExpensifyTests.debugadhoc.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -1117,9 +1141,9 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Debug AdHoc"; + name = DebugAdHoc; }; - CF9AF94729EE928E001FA527 /* Release Production */ = { + CF9AF94729EE928E001FA527 /* ReleaseProduction */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -1176,11 +1200,11 @@ SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; - name = "Release Production"; + name = ReleaseProduction; }; - CF9AF94829EE928E001FA527 /* Release Production */ = { + CF9AF94829EE928E001FA527 /* ReleaseProduction */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 34A8FDD1F9AA58B8F15C8380 /* Pods-NewExpensify.release production.xcconfig */; + baseConfigurationReference = 47D5DF3C6779D41BE70CD031 /* Pods-NewExpensify.releaseproduction.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -1206,11 +1230,11 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Release Production"; + name = ReleaseProduction; }; - CF9AF94929EE928E001FA527 /* Release Production */ = { + CF9AF94929EE928E001FA527 /* ReleaseProduction */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 96552D489D9F09B6A5ABD81B /* Pods-NewExpensify-NewExpensifyTests.release production.xcconfig */; + baseConfigurationReference = 57DBBEDB9692E096D4BA0141 /* Pods-NewExpensify-NewExpensifyTests.releaseproduction.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -1229,9 +1253,9 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Release Production"; + name = ReleaseProduction; }; - CF9AF94D29EE9293001FA527 /* Release AdHoc */ = { + CF9AF94D29EE9293001FA527 /* ReleaseAdHoc */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -1288,11 +1312,11 @@ SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; - name = "Release AdHoc"; + name = ReleaseAdHoc; }; - CF9AF94E29EE9293001FA527 /* Release AdHoc */ = { + CF9AF94E29EE9293001FA527 /* ReleaseAdHoc */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1DDE5449979A136852B939B5 /* Pods-NewExpensify.release adhoc.xcconfig */; + baseConfigurationReference = BD8828A882E2D6B51362AAC3 /* Pods-NewExpensify.releaseadhoc.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIconAdHoc; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; @@ -1318,11 +1342,11 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; - name = "Release AdHoc"; + name = ReleaseAdHoc; }; - CF9AF94F29EE9293001FA527 /* Release AdHoc */ = { + CF9AF94F29EE9293001FA527 /* ReleaseAdHoc */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6B5211DB0EEB46E12DF4AD2D /* Pods-NewExpensify-NewExpensifyTests.release adhoc.xcconfig */; + baseConfigurationReference = E2C8555C607612465A7473F8 /* Pods-NewExpensify-NewExpensifyTests.releaseadhoc.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -1341,7 +1365,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NewExpensify.app/NewExpensify"; }; - name = "Release AdHoc"; + name = ReleaseAdHoc; }; /* End XCBuildConfiguration section */ @@ -1349,41 +1373,41 @@ 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "NewExpensifyTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 00E356F61AD99517003FC87E /* Debug Development */, - CF9AF94629EE927A001FA527 /* Debug AdHoc */, - CF9AF94029EE9276001FA527 /* Debug Production */, - 00E356F71AD99517003FC87E /* Release Development */, - CF9AF94F29EE9293001FA527 /* Release AdHoc */, - CF9AF94929EE928E001FA527 /* Release Production */, + 00E356F61AD99517003FC87E /* DebugDevelopment */, + CF9AF94629EE927A001FA527 /* DebugAdHoc */, + CF9AF94029EE9276001FA527 /* DebugProduction */, + 00E356F71AD99517003FC87E /* ReleaseDevelopment */, + CF9AF94F29EE9293001FA527 /* ReleaseAdHoc */, + CF9AF94929EE928E001FA527 /* ReleaseProduction */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = "Debug Development"; + defaultConfigurationName = DebugDevelopment; }; 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NewExpensify" */ = { isa = XCConfigurationList; buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug Development */, - CF9AF94529EE927A001FA527 /* Debug AdHoc */, - CF9AF93F29EE9276001FA527 /* Debug Production */, - 13B07F951A680F5B00A75B9A /* Release Development */, - CF9AF94E29EE9293001FA527 /* Release AdHoc */, - CF9AF94829EE928E001FA527 /* Release Production */, + 13B07F941A680F5B00A75B9A /* DebugDevelopment */, + CF9AF94529EE927A001FA527 /* DebugAdHoc */, + CF9AF93F29EE9276001FA527 /* DebugProduction */, + 13B07F951A680F5B00A75B9A /* ReleaseDevelopment */, + CF9AF94E29EE9293001FA527 /* ReleaseAdHoc */, + CF9AF94829EE928E001FA527 /* ReleaseProduction */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = "Debug Development"; + defaultConfigurationName = DebugDevelopment; }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NewExpensify" */ = { isa = XCConfigurationList; buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug Development */, - CF9AF94429EE927A001FA527 /* Debug AdHoc */, - CF9AF93E29EE9276001FA527 /* Debug Production */, - 83CBBA211A601CBA00E9B192 /* Release Development */, - CF9AF94D29EE9293001FA527 /* Release AdHoc */, - CF9AF94729EE928E001FA527 /* Release Production */, + 83CBBA201A601CBA00E9B192 /* DebugDevelopment */, + CF9AF94429EE927A001FA527 /* DebugAdHoc */, + CF9AF93E29EE9276001FA527 /* DebugProduction */, + 83CBBA211A601CBA00E9B192 /* ReleaseDevelopment */, + CF9AF94D29EE9293001FA527 /* ReleaseAdHoc */, + CF9AF94729EE928E001FA527 /* ReleaseProduction */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = "Debug Development"; + defaultConfigurationName = DebugDevelopment; }; /* End XCConfigurationList section */ }; diff --git a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify AdHoc.xcscheme b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify AdHoc.xcscheme index 0e0fad6399a0..6cd590456eed 100644 --- a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify AdHoc.xcscheme +++ b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify AdHoc.xcscheme @@ -57,7 +57,7 @@ @@ -75,7 +75,7 @@ + buildConfiguration = "DebugAdHoc"> diff --git a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify Dev.xcscheme b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify Dev.xcscheme index 77f512242f67..93d775217f11 100644 --- a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify Dev.xcscheme +++ b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify Dev.xcscheme @@ -23,7 +23,7 @@ @@ -41,7 +41,7 @@ + buildConfiguration = "DebugDevelopment"> diff --git a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify.xcscheme b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify.xcscheme index f68be2705527..b6b5874506a8 100644 --- a/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify.xcscheme +++ b/ios/NewExpensify.xcodeproj/xcshareddata/xcschemes/New Expensify.xcscheme @@ -75,7 +75,7 @@ + buildConfiguration = "DebugProduction"> diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 00b380a7d1dc..9e4501eddea5 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.67 + 1.3.70 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.3.67.2 + 1.3.70.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 031ce55e7518..fd93684a1da3 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.3.67 + 1.3.70 CFBundleSignature ???? CFBundleVersion - 1.3.67.2 + 1.3.70.2 diff --git a/ios/Podfile b/ios/Podfile index 6445685db014..b30510572448 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -22,7 +22,7 @@ prepare_react_native_project! # dependencies: { # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), # ``` -flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled(['Debug Production', 'Debug Development', 'Debug AdHoc']) +flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled(['DebugProduction', 'DebugDevelopment', 'DebugAdHoc']) linkage = ENV['USE_FRAMEWORKS'] if linkage != nil @@ -54,12 +54,12 @@ target 'NewExpensify' do permissions_path = '../node_modules/react-native-permissions/ios' project 'NewExpensify', - 'Debug Development' => :debug, - 'Debug AdHoc' => :debug, - 'Debug Production' => :debug, - 'Release Development' => :release, - 'Release AdHoc' => :release, - 'Release Production' => :release + 'DebugDevelopment' => :debug, + 'DebugAdHoc' => :debug, + 'DebugProduction' => :debug, + 'ReleaseDevelopment' => :release, + 'ReleaseAdHoc' => :release, + 'ReleaseProduction' => :release pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy" pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways" diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 2bea672171fe..aeb1887223cd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1309,6 +1309,6 @@ SPEC CHECKSUMS: Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 845537d35601574adcd0794e17003ba7dbccdbfd +PODFILE CHECKSUM: 2daf34c870819a933f3fefe426801d54b2ff2a14 COCOAPODS: 1.12.1 diff --git a/package-lock.json b/package-lock.json index cd763dffefbe..f36d0e88f52b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "new.expensify", - "version": "1.3.67-2", + "version": "1.3.70-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.67-2", + "version": "1.3.70-2", "hasInstallScript": true, "license": "MIT", "dependencies": { "@expensify/react-native-web": "0.18.15", + "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-getcanonicallocales": "^2.2.0", "@formatjs/intl-listformat": "^7.2.2", "@formatjs/intl-locale": "^3.3.0", @@ -18,6 +19,8 @@ "@formatjs/intl-pluralrules": "^5.2.2", "@gorhom/portal": "^1.0.14", "@invertase/react-native-apple-authentication": "^2.2.2", + "@kie/act-js": "^2.0.1", + "@kie/mock-github": "^1.0.0", "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", "@onfido/react-native-sdk": "7.4.0", "@react-native-async-storage/async-storage": "^1.17.10", @@ -36,6 +39,7 @@ "@react-navigation/stack": "6.3.16", "@react-ng/bounds-observer": "^0.2.1", "@rnmapbox/maps": "^10.0.11", + "@types/node": "^18.14.0", "@ua/react-native-airship": "^15.2.6", "awesome-phonenumber": "^5.4.0", "babel-plugin-transform-remove-console": "^6.9.4", @@ -46,8 +50,9 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#e63d06e239fe5b2f221e86eab71ae8a4e3b8bee3", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086", "fbjs": "^3.0.2", + "focus-trap-react": "^10.2.1", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", "jest-when": "^3.5.2", @@ -85,7 +90,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.72", + "react-native-onyx": "1.0.76", "react-native-pager-view": "^6.2.0", "react-native-pdf": "^6.7.1", "react-native-performance": "^4.0.0", @@ -128,6 +133,8 @@ "@babel/runtime": "^7.20.0", "@electron/notarize": "^1.2.3", "@jest/globals": "^29.5.0", + "@kie/act-js": "^2.0.1", + "@kie/mock-github": "^1.0.0", "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", @@ -179,8 +186,8 @@ "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", - "electron": "^25.8.0", - "electron-builder": "24.5.0", + "electron": "^25.8.1", + "electron-builder": "24.6.4", "eslint": "^7.6.0", "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-expensify": "^2.0.38", @@ -221,7 +228,8 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.9.3", "webpack-font-preload-plugin": "^1.5.0", - "webpack-merge": "^5.8.0" + "webpack-merge": "^5.8.0", + "yaml": "^2.2.1" }, "engines": { "node": "16.15.1", @@ -2953,9 +2961,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.4.tgz", - "integrity": "sha512-xfhdEcIOfAZg7scZ9RQPya1G1lWo8/zMCwUXAulq0SfY7ONIW+b9qGyKdMyuMctNYwllrIS+vmxfijSfjeh97g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", "dev": true, "dependencies": { "compare-version": "^0.1.2", @@ -2999,171 +3007,10 @@ "url": "https://github.com/sponsors/gjtorikian/" } }, - "node_modules/@electron/rebuild": { - "version": "3.2.13", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.2.13.tgz", - "integrity": "sha512-DH9Ol4JCnHDYVOD0fKWq+Qqbn/0WU1O6QR0mIpMXEVU4YFM4PlaqNC9K36mGShNBxxGFotZCMDrB1wl/iHM12g==", - "dev": true, - "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@electron/rebuild/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@electron/rebuild/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@electron/rebuild/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@electron/rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@electron/rebuild/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@electron/rebuild/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/rebuild/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@electron/rebuild/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@electron/universal": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.3.4.tgz", - "integrity": "sha512-BdhBgm2ZBnYyYRLRgOjM5VHkyFItsbggJ0MHycOjKWdFGYwK97ZFXH54dTvUWEfha81vfvwr5On6XBjt99uDcg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz", + "integrity": "sha512-lE/U3UNw1YHuowNbTmKNs9UlS3En3cPgwM5MI+agIgr/B1hSze9NdOP0qn7boZaI9Lph8IDv3/24g9IxnJP7aQ==", "dev": true, "dependencies": { "@electron/asar": "^3.2.1", @@ -3178,28 +3025,6 @@ "node": ">=8.6" } }, - "node_modules/@electron/universal/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", @@ -3871,6 +3696,33 @@ "tslib": "^2.4.0" } }, + "node_modules/@formatjs/intl-datetimeformat": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl-datetimeformat/-/intl-datetimeformat-6.10.0.tgz", + "integrity": "sha512-5tJWZxOyP5D4PDrqv27h0LWAPHhQM9BHR0pDBTZOKWFEZNrS2IgREbyalSGwQLtN1tZaDrt3YeNfNLbZk1wSUw==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.17.0", + "@formatjs/intl-localematcher": "0.4.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-datetimeformat/node_modules/@formatjs/ecma402-abstract": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.0.tgz", + "integrity": "sha512-6ueQTeJZtwKjmh23bdkq/DMqH4l4bmfvtQH98blOSbiXv/OUiyijSW6jU22IT8BNM1ujCaEvJfTtyCYVH38EMQ==", + "dependencies": { + "@formatjs/intl-localematcher": "0.4.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-datetimeformat/node_modules/@formatjs/intl-localematcher": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.4.0.tgz", + "integrity": "sha512-bRTd+rKomvfdS4QDlVJ6TA/Jx1F2h/TBVO5LjvhQ7QPPHp19oPNMIum7W2CMEReq/zPxpmCeB31F9+5gl/qtvw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@formatjs/intl-enumerator": { "version": "1.3.0", "license": "MIT", @@ -5376,6 +5228,110 @@ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", "dev": true }, + "node_modules/@kie/act-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@kie/act-js/-/act-js-2.3.0.tgz", + "integrity": "sha512-Q9k0b05uA46jXKWmVfoGDW+0xsCcE7QPiHi8IH7h41P36DujHKBj4k28RCeIEx3IwUCxYHKwubN8DH4Vzc9XcA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@kie/mock-github": "^2.0.0", + "adm-zip": "^0.5.10", + "ajv": "^8.12.0", + "bin-links": "^4.0.1", + "express": "^4.18.1", + "follow-redirects": "^1.15.2", + "tar": "^6.1.13", + "yaml": "^2.1.3" + }, + "bin": { + "act-js": "bin/act" + } + }, + "node_modules/@kie/act-js/node_modules/@kie/mock-github": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@kie/mock-github/-/mock-github-2.0.0.tgz", + "integrity": "sha512-od6UyICJYKMnz9HgEWCQAFT/JsCpKkLp+JQH8fV23tf+ZmmQI1dK3C20k6aO5uJhAHA0yOcFtbKFVF4+8i3DTg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types-ghec": "^18.0.0", + "ajv": "^8.11.0", + "express": "^4.18.1", + "fast-glob": "^3.2.12", + "fs-extra": "^10.1.0", + "nock": "^13.2.7", + "simple-git": "^3.8.0", + "totalist": "^3.0.0" + } + }, + "node_modules/@kie/act-js/node_modules/@octokit/openapi-types-ghec": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types-ghec/-/openapi-types-ghec-18.0.0.tgz", + "integrity": "sha512-xY5FTR/DW2gUJdC5GyzkqrfMHhr3u3hg+dUG6bA5FvuuODw6A7+0JTTSS1ndLQEKGmFxP7chf1BKkhvhnqxCew==", + "dev": true + }, + "node_modules/@kie/act-js/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@kie/act-js/node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@kie/mock-github": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@kie/mock-github/-/mock-github-1.1.0.tgz", + "integrity": "sha512-fD+utlOiyZSOutOcXL0G9jfjbtvOO44PLUyTfgfkrm1+575R/dbvU6AcJfjc1DtHeRv7FC7f4ebyU+a1wgL6CA==", + "dev": true, + "dependencies": { + "@octokit/openapi-types-ghec": "^14.0.0", + "ajv": "^8.11.0", + "express": "^4.18.1", + "fast-glob": "^3.2.12", + "fs-extra": "^10.1.0", + "nock": "^13.2.7", + "simple-git": "^3.8.0", + "totalist": "^3.0.0" + } + }, + "node_modules/@kie/mock-github/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@kie/mock-github/node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -5412,9 +5368,9 @@ } }, "node_modules/@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", "dev": true, "funding": [ { @@ -5430,7 +5386,7 @@ "cross-spawn": "^7.0.1" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10" } }, "node_modules/@malept/flatpak-bundler": { @@ -5882,6 +5838,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@octokit/openapi-types-ghec": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types-ghec/-/openapi-types-ghec-14.0.0.tgz", + "integrity": "sha512-xhd9oEvn2aroGn+sk09Ptx/76Y7aKU0EIgHukHPCU1+rGJreO36baEEk6k8ZPblieHNM39FcykJQmtDrETm0KA==", + "dev": true + }, "node_modules/@octokit/plugin-paginate-rest": { "version": "3.1.0", "dev": true, @@ -7112,14 +7074,6 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "engines": { - "node": ">= 14" - } - }, "node_modules/@react-native-community/cli-hermes": { "version": "11.3.5", "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-11.3.5.tgz", @@ -19477,7 +19431,9 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -19561,6 +19517,15 @@ "node": ">= 10.0.0" } }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "dev": true, @@ -19572,20 +19537,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "dev": true, @@ -19874,16 +19825,15 @@ "dev": true }, "node_modules/app-builder-lib": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.5.0.tgz", - "integrity": "sha512-f8R0aWIl5/JVipwP9QvEDIuebo191zGTco/aEdJQpMinQaIZSIS3U8kt1vZxYe7kGXZ3S0zNf6h7SMcWKRLzcQ==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.6.4.tgz", + "integrity": "sha512-m9931WXb83teb32N0rKg+ulbn6+Hl8NV5SUpVDOVz9MWOXfhV6AQtTdftf51zJJvCQnQugGtSqoLvgw6mdF/Rg==", "dev": true, "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "^1.2.3", - "@electron/osx-sign": "^1.0.4", - "@electron/rebuild": "^3.2.13", - "@electron/universal": "1.3.4", + "@electron/notarize": "2.1.0", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.4.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "7zip-bin": "~5.1.1", @@ -19913,6 +19863,35 @@ "node": ">=14.0.0" } }, + "node_modules/app-builder-lib/node_modules/@electron/notarize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.1.0.tgz", + "integrity": "sha512-Q02xem1D0sg4v437xHgmBLxI2iz/fc0D4K7fiVWHa/AnW8o7D751xyKNXgziA6HrTOme9ul1JfWN5ark8WH1xA==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/app-builder-lib/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -21384,6 +21363,46 @@ "node": "*" } }, + "node_modules/bin-links": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.2.tgz", + "integrity": "sha512-jxJ0PbXR8eQyPlExCvCs3JFnikvs1Yp4gUJt6nmgathdOwvur+q22KWC3h20gvWl4T/14DXKj2IlkJwwZkZPOw==", + "dev": true, + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/bin-links/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/bin-links/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "devOptional": true, @@ -22817,6 +22836,15 @@ "node": ">=6" } }, + "node_modules/cmd-shim": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.1.tgz", + "integrity": "sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/co": { "version": "4.6.0", "license": "MIT", @@ -23471,6 +23499,15 @@ "node": ">=10" } }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/cp-file": { "version": "7.0.0", "dev": true, @@ -24600,6 +24637,8 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -24712,12 +24751,12 @@ } }, "node_modules/dmg-builder": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.5.0.tgz", - "integrity": "sha512-xQHaXMALL85hQJVR2CKMmN8xibjwo2Ukjpj7aape/mAfE+w7E5RNg0nD/RVQ5uj5AHPySVFHiCGrAkjXjUPOcw==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.6.4.tgz", + "integrity": "sha512-BNcHRc9CWEuI9qt0E655bUBU/j/3wUCYBVKGu1kVpbN5lcUdEJJJeiO0NHK3dgKmra6LUUZlo+mWqc+OCbi0zw==", "dev": true, "dependencies": { - "app-builder-lib": "24.5.0", + "app-builder-lib": "24.6.4", "builder-util": "24.5.0", "builder-util-runtime": "9.2.1", "fs-extra": "^10.1.0", @@ -25005,9 +25044,9 @@ } }, "node_modules/electron": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.0.tgz", - "integrity": "sha512-T3kC1a/3ntSaYMCVVfUUc9v7myPzi6J2GP0Ad/CyfWKDPp054dGyKxb2EEjKnxQQ7wfjsT1JTEdBG04x6ekVBw==", + "version": "25.8.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.1.tgz", + "integrity": "sha512-GtcP1nMrROZfFg0+mhyj1hamrHvukfF6of2B/pcWxmWkd5FVY1NJib0tlhiorFZRzQN5Z+APLPr7aMolt7i2AQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -25023,21 +25062,21 @@ } }, "node_modules/electron-builder": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.5.0.tgz", - "integrity": "sha512-IyF6aYq5zcTz15ZkUK/PuFs3nW/fSR68ZgC/3ac32exw4ivQI0FlZLIEkJLpfI43pUFTtnvwv9Wsm1iDSf9aPw==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.6.4.tgz", + "integrity": "sha512-uNWQoU7pE7qOaIQ6CJHpBi44RJFVG8OHRBIadUxrsDJVwLLo8Nma3K/EEtx5/UyWAQYdcK4nVPYKoRqBb20hbA==", "dev": true, "dependencies": { - "app-builder-lib": "24.5.0", + "app-builder-lib": "24.6.4", "builder-util": "24.5.0", "builder-util-runtime": "9.2.1", "chalk": "^4.1.2", - "dmg-builder": "24.5.0", + "dmg-builder": "24.6.4", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "read-config-file": "6.3.2", - "simple-update-notifier": "^1.1.0", + "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { @@ -25342,6 +25381,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -27479,8 +27519,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#e63d06e239fe5b2f221e86eab71ae8a4e3b8bee3", - "integrity": "sha512-ufptwN4Ef0JiBwvit3qN9zY8y6gFQHlMJWe+Poc0cQ0XcAuYIFSxbE0cAojMuRw7eA1to87JKKF028APIXRM/Q==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086", + "integrity": "sha512-O0KbaMljSFyoZXcxtx5B2qBL+n0md3wYOrArMVT8N0W+4wKncn+p8/vrmVlUMHe/vDloUbVmUZNdHwOZNWdx3w==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -27562,12 +27602,6 @@ "version": "1.13.1", "license": "MIT" }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, "node_modules/express": { "version": "4.18.1", "dev": true, @@ -28261,8 +28295,32 @@ "readable-stream": "^2.3.6" } }, + "node_modules/focus-trap": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz", + "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==", + "dependencies": { + "tabbable": "^6.2.0" + } + }, + "node_modules/focus-trap-react": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-10.2.1.tgz", + "integrity": "sha512-UrAKOn52lvfHF6lkUMfFhlQxFgahyNW5i6FpHWkDxAeD4FSk3iwx9n4UEA4Sims0G5WiGIi0fAyoq3/UVeNCYA==", + "dependencies": { + "focus-trap": "^7.5.2", + "tabbable": "^6.2.0" + }, + "peerDependencies": { + "prop-types": "^15.8.1", + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, "node_modules/follow-redirects": { - "version": "1.15.1", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "dev": true, "funding": [ { @@ -28270,7 +28328,6 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], - "license": "MIT", "engines": { "node": ">=4.0" }, @@ -28469,6 +28526,15 @@ "node": ">=8" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/form-data": { "version": "3.0.1", "dev": true, @@ -29756,15 +29822,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/husky": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", @@ -30802,12 +30859,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, "node_modules/is-map": { "version": "2.0.2", "dev": true, @@ -34607,234 +34658,6 @@ "url": "https://github.com/wojtekmaj/make-event-props?sponsor=1" } }, - "node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/cacache/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/make-fetch-happen/node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/make-fetch-happen/node_modules/glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/make-fetch-happen/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/makeerror": { "version": "1.0.12", "license": "BSD-3-Clause", @@ -37640,32 +37463,6 @@ "node": ">= 8" } }, - "node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "dependencies": { - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/minipass-flush": { "version": "1.0.5", "dev": true, @@ -37688,18 +37485,6 @@ "node": ">=8" } }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/minizlib": { "version": "2.1.2", "dev": true, @@ -37985,16 +37770,19 @@ "node": ">=12.0.0" } }, - "node_modules/node-abi": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", - "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "node_modules/nock": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.3.tgz", + "integrity": "sha512-z+KUlILy9SK/RjpeXDiDUEAq4T94ADPHE3qaRkf66mpEhzc/ytOMm3Bwdrbq6k1tMWkbdujiKim3G2tfQARuJw==", "dev": true, "dependencies": { - "semver": "^7.3.5" + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.21", + "propagate": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">= 10.13" } }, "node_modules/node-abort-controller": { @@ -38009,15 +37797,6 @@ "dev": true, "optional": true }, - "node_modules/node-api-version": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", - "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - } - }, "node_modules/node-dir": { "version": "0.1.17", "license": "MIT", @@ -38070,92 +37849,6 @@ "node": ">= 6.13.0" } }, - "node_modules/node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/node-int64": { "version": "0.4.0", "license": "MIT" @@ -38223,21 +37916,6 @@ "url": "https://github.com/sponsors/antelle" } }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/normalize-css-color": { "version": "1.0.2", "license": "BSD-3-Clause" @@ -38290,6 +37968,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "license": "MIT", @@ -39260,14 +38947,6 @@ "node": ">=0.6.0" } }, - "node_modules/patch-package/node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "engines": { - "node": ">= 14" - } - }, "node_modules/path-browserify": { "version": "0.0.1", "license": "MIT" @@ -39966,6 +39645,15 @@ "react-is": "^16.13.1" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/property-information": { "version": "5.6.0", "dev": true, @@ -40884,9 +40572,9 @@ } }, "node_modules/react-native-onyx": { - "version": "1.0.72", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.72.tgz", - "integrity": "sha512-roJuA92qZH2PLYSqBhSPCse+Ra2EJu4FBpVqguwJRp6oaLNHR1CtPTgU1xMh/kj2nWmdpcqKoOc3nS35asb80g==", + "version": "1.0.76", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.76.tgz", + "integrity": "sha512-mcMlYQCo1B/kom+4hu7CQKKLwvPFjQAJsVIzV2s9aa8XKNlcnYiJbfuM6RSJ1fFmSIeud4Y66rhv4/oWUkSl5A==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -41976,6 +41664,15 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/read-config-file": { "version": "6.3.2", "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", @@ -43780,24 +43477,15 @@ "license": "MIT" }, "node_modules/simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, "dependencies": { - "semver": "~7.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "node_modules/simply-deferred": { @@ -43888,6 +43576,7 @@ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, + "optional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -44117,34 +43806,6 @@ "websocket-driver": "^0.7.4" } }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/sort-asc": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", @@ -45036,6 +44697,11 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "node_modules/table": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", @@ -48306,11 +47972,11 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", - "dev": true, - "license": "ISC", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", + "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/yargs": { @@ -50303,9 +49969,9 @@ } }, "@electron/osx-sign": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.4.tgz", - "integrity": "sha512-xfhdEcIOfAZg7scZ9RQPya1G1lWo8/zMCwUXAulq0SfY7ONIW+b9qGyKdMyuMctNYwllrIS+vmxfijSfjeh97g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", "dev": true, "requires": { "compare-version": "^0.1.2", @@ -50335,131 +50001,10 @@ } } }, - "@electron/rebuild": { - "version": "3.2.13", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.2.13.tgz", - "integrity": "sha512-DH9Ol4JCnHDYVOD0fKWq+Qqbn/0WU1O6QR0mIpMXEVU4YFM4PlaqNC9K36mGShNBxxGFotZCMDrB1wl/iHM12g==", - "dev": true, - "requires": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, "@electron/universal": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.3.4.tgz", - "integrity": "sha512-BdhBgm2ZBnYyYRLRgOjM5VHkyFItsbggJ0MHycOjKWdFGYwK97ZFXH54dTvUWEfha81vfvwr5On6XBjt99uDcg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz", + "integrity": "sha512-lE/U3UNw1YHuowNbTmKNs9UlS3En3cPgwM5MI+agIgr/B1hSze9NdOP0qn7boZaI9Lph8IDv3/24g9IxnJP7aQ==", "dev": true, "requires": { "@electron/asar": "^3.2.1", @@ -50469,17 +50014,6 @@ "fs-extra": "^9.0.1", "minimatch": "^3.0.4", "plist": "^3.0.4" - }, - "dependencies": { - "@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - } } }, "@emotion/use-insertion-effect-with-fallbacks": { @@ -50871,6 +50405,35 @@ "tslib": "^2.4.0" } }, + "@formatjs/intl-datetimeformat": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl-datetimeformat/-/intl-datetimeformat-6.10.0.tgz", + "integrity": "sha512-5tJWZxOyP5D4PDrqv27h0LWAPHhQM9BHR0pDBTZOKWFEZNrS2IgREbyalSGwQLtN1tZaDrt3YeNfNLbZk1wSUw==", + "requires": { + "@formatjs/ecma402-abstract": "1.17.0", + "@formatjs/intl-localematcher": "0.4.0", + "tslib": "^2.4.0" + }, + "dependencies": { + "@formatjs/ecma402-abstract": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.0.tgz", + "integrity": "sha512-6ueQTeJZtwKjmh23bdkq/DMqH4l4bmfvtQH98blOSbiXv/OUiyijSW6jU22IT8BNM1ujCaEvJfTtyCYVH38EMQ==", + "requires": { + "@formatjs/intl-localematcher": "0.4.0", + "tslib": "^2.4.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.4.0.tgz", + "integrity": "sha512-bRTd+rKomvfdS4QDlVJ6TA/Jx1F2h/TBVO5LjvhQ7QPPHp19oPNMIum7W2CMEReq/zPxpmCeB31F9+5gl/qtvw==", + "requires": { + "tslib": "^2.4.0" + } + } + } + }, "@formatjs/intl-enumerator": { "version": "1.3.0", "requires": { @@ -51947,6 +51510,98 @@ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", "dev": true }, + "@kie/act-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@kie/act-js/-/act-js-2.3.0.tgz", + "integrity": "sha512-Q9k0b05uA46jXKWmVfoGDW+0xsCcE7QPiHi8IH7h41P36DujHKBj4k28RCeIEx3IwUCxYHKwubN8DH4Vzc9XcA==", + "dev": true, + "requires": { + "@kie/mock-github": "^2.0.0", + "adm-zip": "^0.5.10", + "ajv": "^8.12.0", + "bin-links": "^4.0.1", + "express": "^4.18.1", + "follow-redirects": "^1.15.2", + "tar": "^6.1.13", + "yaml": "^2.1.3" + }, + "dependencies": { + "@kie/mock-github": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@kie/mock-github/-/mock-github-2.0.0.tgz", + "integrity": "sha512-od6UyICJYKMnz9HgEWCQAFT/JsCpKkLp+JQH8fV23tf+ZmmQI1dK3C20k6aO5uJhAHA0yOcFtbKFVF4+8i3DTg==", + "dev": true, + "requires": { + "@octokit/openapi-types-ghec": "^18.0.0", + "ajv": "^8.11.0", + "express": "^4.18.1", + "fast-glob": "^3.2.12", + "fs-extra": "^10.1.0", + "nock": "^13.2.7", + "simple-git": "^3.8.0", + "totalist": "^3.0.0" + } + }, + "@octokit/openapi-types-ghec": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types-ghec/-/openapi-types-ghec-18.0.0.tgz", + "integrity": "sha512-xY5FTR/DW2gUJdC5GyzkqrfMHhr3u3hg+dUG6bA5FvuuODw6A7+0JTTSS1ndLQEKGmFxP7chf1BKkhvhnqxCew==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true + } + } + }, + "@kie/mock-github": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@kie/mock-github/-/mock-github-1.1.0.tgz", + "integrity": "sha512-fD+utlOiyZSOutOcXL0G9jfjbtvOO44PLUyTfgfkrm1+575R/dbvU6AcJfjc1DtHeRv7FC7f4ebyU+a1wgL6CA==", + "dev": true, + "requires": { + "@octokit/openapi-types-ghec": "^14.0.0", + "ajv": "^8.11.0", + "express": "^4.18.1", + "fast-glob": "^3.2.12", + "fs-extra": "^10.1.0", + "nock": "^13.2.7", + "simple-git": "^3.8.0", + "totalist": "^3.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true + } + } + }, "@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -51974,9 +51629,9 @@ } }, "@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", "dev": true, "requires": { "cross-spawn": "^7.0.1" @@ -52329,6 +51984,12 @@ "version": "12.11.0", "dev": true }, + "@octokit/openapi-types-ghec": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types-ghec/-/openapi-types-ghec-14.0.0.tgz", + "integrity": "sha512-xhd9oEvn2aroGn+sk09Ptx/76Y7aKU0EIgHukHPCU1+rGJreO36baEEk6k8ZPblieHNM39FcykJQmtDrETm0KA==", + "dev": true + }, "@octokit/plugin-paginate-rest": { "version": "3.1.0", "dev": true, @@ -53242,11 +52903,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" } } }, @@ -61899,7 +61555,9 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "abort-controller": { "version": "3.0.0", @@ -61950,6 +61608,12 @@ "version": "1.2.1", "dev": true }, + "adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true + }, "agent-base": { "version": "6.0.2", "dev": true, @@ -61957,17 +61621,6 @@ "debug": "4" } }, - "agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - } - }, "aggregate-error": { "version": "3.1.0", "dev": true, @@ -62161,16 +61814,15 @@ "dev": true }, "app-builder-lib": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.5.0.tgz", - "integrity": "sha512-f8R0aWIl5/JVipwP9QvEDIuebo191zGTco/aEdJQpMinQaIZSIS3U8kt1vZxYe7kGXZ3S0zNf6h7SMcWKRLzcQ==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.6.4.tgz", + "integrity": "sha512-m9931WXb83teb32N0rKg+ulbn6+Hl8NV5SUpVDOVz9MWOXfhV6AQtTdftf51zJJvCQnQugGtSqoLvgw6mdF/Rg==", "dev": true, "requires": { "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "^1.2.3", - "@electron/osx-sign": "^1.0.4", - "@electron/rebuild": "^3.2.13", - "@electron/universal": "1.3.4", + "@electron/notarize": "2.1.0", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.4.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "7zip-bin": "~5.1.1", @@ -62197,6 +61849,31 @@ "temp-file": "^3.4.0" }, "dependencies": { + "@electron/notarize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.1.0.tgz", + "integrity": "sha512-Q02xem1D0sg4v437xHgmBLxI2iz/fc0D4K7fiVWHa/AnW8o7D751xyKNXgziA6HrTOme9ul1JfWN5ark8WH1xA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -63236,6 +62913,36 @@ "version": "5.2.2", "devOptional": true }, + "bin-links": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.2.tgz", + "integrity": "sha512-jxJ0PbXR8eQyPlExCvCs3JFnikvs1Yp4gUJt6nmgathdOwvur+q22KWC3h20gvWl4T/14DXKj2IlkJwwZkZPOw==", + "dev": true, + "requires": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + } + } + } + }, "binary-extensions": { "version": "2.2.0", "devOptional": true @@ -64211,6 +63918,12 @@ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" }, + "cmd-shim": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.1.tgz", + "integrity": "sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q==", + "dev": true + }, "co": { "version": "4.6.0" }, @@ -64645,6 +64358,14 @@ "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" + }, + "dependencies": { + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + } } }, "cp-file": { @@ -65417,7 +65138,9 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "detect-newline": { "version": "3.1.0" @@ -65498,12 +65221,12 @@ } }, "dmg-builder": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.5.0.tgz", - "integrity": "sha512-xQHaXMALL85hQJVR2CKMmN8xibjwo2Ukjpj7aape/mAfE+w7E5RNg0nD/RVQ5uj5AHPySVFHiCGrAkjXjUPOcw==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.6.4.tgz", + "integrity": "sha512-BNcHRc9CWEuI9qt0E655bUBU/j/3wUCYBVKGu1kVpbN5lcUdEJJJeiO0NHK3dgKmra6LUUZlo+mWqc+OCbi0zw==", "dev": true, "requires": { - "app-builder-lib": "24.5.0", + "app-builder-lib": "24.6.4", "builder-util": "24.5.0", "builder-util-runtime": "9.2.1", "dmg-license": "^1.0.11", @@ -65715,9 +65438,9 @@ } }, "electron": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.0.tgz", - "integrity": "sha512-T3kC1a/3ntSaYMCVVfUUc9v7myPzi6J2GP0Ad/CyfWKDPp054dGyKxb2EEjKnxQQ7wfjsT1JTEdBG04x6ekVBw==", + "version": "25.8.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.8.1.tgz", + "integrity": "sha512-GtcP1nMrROZfFg0+mhyj1hamrHvukfF6of2B/pcWxmWkd5FVY1NJib0tlhiorFZRzQN5Z+APLPr7aMolt7i2AQ==", "dev": true, "requires": { "@electron/get": "^2.0.0", @@ -65726,21 +65449,21 @@ } }, "electron-builder": { - "version": "24.5.0", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.5.0.tgz", - "integrity": "sha512-IyF6aYq5zcTz15ZkUK/PuFs3nW/fSR68ZgC/3ac32exw4ivQI0FlZLIEkJLpfI43pUFTtnvwv9Wsm1iDSf9aPw==", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.6.4.tgz", + "integrity": "sha512-uNWQoU7pE7qOaIQ6CJHpBi44RJFVG8OHRBIadUxrsDJVwLLo8Nma3K/EEtx5/UyWAQYdcK4nVPYKoRqBb20hbA==", "dev": true, "requires": { - "app-builder-lib": "24.5.0", + "app-builder-lib": "24.6.4", "builder-util": "24.5.0", "builder-util-runtime": "9.2.1", "chalk": "^4.1.2", - "dmg-builder": "24.5.0", + "dmg-builder": "24.6.4", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "read-config-file": "6.3.2", - "simple-update-notifier": "^1.1.0", + "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "dependencies": { @@ -65957,6 +65680,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "optional": true, + "peer": true, "requires": { "iconv-lite": "^0.6.2" } @@ -67438,9 +67162,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#e63d06e239fe5b2f221e86eab71ae8a4e3b8bee3", - "integrity": "sha512-ufptwN4Ef0JiBwvit3qN9zY8y6gFQHlMJWe+Poc0cQ0XcAuYIFSxbE0cAojMuRw7eA1to87JKKF028APIXRM/Q==", - "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#e63d06e239fe5b2f221e86eab71ae8a4e3b8bee3", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086", + "integrity": "sha512-O0KbaMljSFyoZXcxtx5B2qBL+n0md3wYOrArMVT8N0W+4wKncn+p8/vrmVlUMHe/vDloUbVmUZNdHwOZNWdx3w==", + "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", @@ -67498,12 +67222,6 @@ } } }, - "exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, "express": { "version": "4.18.1", "dev": true, @@ -67995,8 +67713,27 @@ "readable-stream": "^2.3.6" } }, + "focus-trap": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz", + "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==", + "requires": { + "tabbable": "^6.2.0" + } + }, + "focus-trap-react": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-10.2.1.tgz", + "integrity": "sha512-UrAKOn52lvfHF6lkUMfFhlQxFgahyNW5i6FpHWkDxAeD4FSk3iwx9n4UEA4Sims0G5WiGIi0fAyoq3/UVeNCYA==", + "requires": { + "focus-trap": "^7.5.2", + "tabbable": "^6.2.0" + } + }, "follow-redirects": { - "version": "1.15.1", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "dev": true }, "for-each": { @@ -68112,6 +67849,12 @@ "requires": { "has-flag": "^4.0.0" } + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true } } }, @@ -68973,15 +68716,6 @@ "human-signals": { "version": "2.1.0" }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, "husky": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", @@ -69638,12 +69372,6 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, "is-map": { "version": "2.0.2", "dev": true @@ -72223,179 +71951,6 @@ "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.6.1.tgz", "integrity": "sha512-JhvWq/iz1BvlmnPvLJjXv+xnMPJZuychrDC68V+yCGQJn5chcA8rLGKo5EP1XwIKVrigSXKLmbeXAGkf36wdCQ==" }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "requires": { - "semver": "^7.3.5" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true - } - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true - } - } - }, - "glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true - } - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, "makeerror": { "version": "1.0.12", "requires": { @@ -74403,26 +73958,6 @@ "minipass": "^3.0.0" } }, - "minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - } - } - }, "minipass-flush": { "version": "1.0.5", "dev": true, @@ -74437,15 +73972,6 @@ "minipass": "^3.0.0" } }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, "minizlib": { "version": "2.1.2", "dev": true, @@ -74645,13 +74171,16 @@ "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==" }, - "node-abi": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", - "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "nock": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.3.tgz", + "integrity": "sha512-z+KUlILy9SK/RjpeXDiDUEAq4T94ADPHE3qaRkf66mpEhzc/ytOMm3Bwdrbq6k1tMWkbdujiKim3G2tfQARuJw==", "dev": true, "requires": { - "semver": "^7.3.5" + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.21", + "propagate": "^2.0.0" } }, "node-abort-controller": { @@ -74666,15 +74195,6 @@ "dev": true, "optional": true }, - "node-api-version": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", - "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", - "dev": true, - "requires": { - "semver": "^7.3.5" - } - }, "node-dir": { "version": "0.1.17", "requires": { @@ -74706,76 +74226,6 @@ "version": "1.3.1", "dev": true }, - "node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "node-int64": { "version": "0.4.0" }, @@ -74833,15 +74283,6 @@ "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==" }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, "normalize-css-color": { "version": "1.0.2" }, @@ -74875,6 +74316,12 @@ "version": "6.1.0", "dev": true }, + "npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true + }, "npm-run-path": { "version": "4.0.1", "requires": { @@ -75506,11 +74953,6 @@ "requires": { "os-tmpdir": "~1.0.2" } - }, - "yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" } } }, @@ -75975,6 +75417,12 @@ "react-is": "^16.13.1" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "property-information": { "version": "5.6.0", "dev": true, @@ -76679,9 +76127,9 @@ } }, "react-native-onyx": { - "version": "1.0.72", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.72.tgz", - "integrity": "sha512-roJuA92qZH2PLYSqBhSPCse+Ra2EJu4FBpVqguwJRp6oaLNHR1CtPTgU1xMh/kj2nWmdpcqKoOc3nS35asb80g==", + "version": "1.0.76", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-1.0.76.tgz", + "integrity": "sha512-mcMlYQCo1B/kom+4hu7CQKKLwvPFjQAJsVIzV2s9aa8XKNlcnYiJbfuM6RSJ1fFmSIeud4Y66rhv4/oWUkSl5A==", "requires": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -77265,6 +76713,12 @@ "memoize-one": ">=3.1.1 <6" } }, + "read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", + "dev": true + }, "read-config-file": { "version": "6.3.2", "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", @@ -78547,20 +78001,12 @@ } }, "simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, "requires": { - "semver": "~7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } + "semver": "^7.5.3" } }, "simply-deferred": { @@ -78628,7 +78074,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true + "dev": true, + "optional": true }, "snapdragon": { "version": "0.8.2", @@ -78791,27 +78238,6 @@ "websocket-driver": "^0.7.4" } }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, "sort-asc": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", @@ -79433,6 +78859,11 @@ "version": "2.0.15", "dev": true }, + "tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, "table": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", @@ -81623,8 +81054,9 @@ "version": "4.0.0" }, "yaml": { - "version": "1.10.2", - "dev": true + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", + "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==" }, "yargs": { "version": "13.3.2", diff --git a/package.json b/package.json index 6666fd19cf7a..315d01ea5dc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.67-2", + "version": "1.3.70-2", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -11,10 +11,10 @@ "postinstall": "scripts/postInstall.sh", "clean": "npx react-native clean-project-auto", "android": "scripts/set-pusher-suffix.sh && npx react-native run-android --variant=developmentDebug --appId=com.expensify.chat.dev", - "ios": "scripts/set-pusher-suffix.sh && npx react-native run-ios --list-devices --configuration=\"Debug Development\" --scheme=\"New Expensify Dev\"", + "ios": "scripts/set-pusher-suffix.sh && npx react-native run-ios --list-devices --configuration=\"DebugDevelopment\" --scheme=\"New Expensify Dev\"", "pod-install": "cd ios && bundle exec pod install", - "ipad": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (12.9-inch) (6th generation)\\\" --configuration=\\\"Debug Development\\\" --scheme=\\\"New Expensify Dev\\\"\"", - "ipad-sm": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (11-inch) (4th generation)\\\" --configuration=\\\"Debug Development\\\" --scheme=\\\"New Expensify Dev\\\"\"", + "ipad": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (12.9-inch) (6th generation)\\\" --configuration=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"", + "ipad-sm": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (11-inch) (4th generation)\\\" --configuration=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"", "start": "npx react-native start", "web": "scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server", "web-proxy": "node web/proxy.js", @@ -47,10 +47,13 @@ "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production", "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", - "test:e2e": "node tests/e2e/testRunner.js --development" + "test:e2e": "node tests/e2e/testRunner.js --development", + "workflow-test": "./workflow_tests/scripts/runWorkflowTests.sh", + "workflow-test:generate": "node workflow_tests/utils/preGenerateTest.js" }, "dependencies": { "@expensify/react-native-web": "0.18.15", + "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-getcanonicallocales": "^2.2.0", "@formatjs/intl-listformat": "^7.2.2", "@formatjs/intl-locale": "^3.3.0", @@ -59,6 +62,8 @@ "@gorhom/portal": "^1.0.14", "@invertase/react-native-apple-authentication": "^2.2.2", "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", + "@kie/act-js": "^2.0.1", + "@kie/mock-github": "^1.0.0", "@onfido/react-native-sdk": "7.4.0", "@react-native-async-storage/async-storage": "^1.17.10", "@react-native-camera-roll/camera-roll": "5.4.0", @@ -78,6 +83,7 @@ "@rnmapbox/maps": "^10.0.11", "@ua/react-native-airship": "^15.2.6", "awesome-phonenumber": "^5.4.0", + "@types/node": "^18.14.0", "babel-plugin-transform-remove-console": "^6.9.4", "babel-polyfill": "^6.26.0", "canvas-size": "^1.2.6", @@ -86,8 +92,9 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#e63d06e239fe5b2f221e86eab71ae8a4e3b8bee3", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#35bff866a8d345b460ea6256f0a0f0a8a7f81086", "fbjs": "^3.0.2", + "focus-trap-react": "^10.2.1", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", "jest-when": "^3.5.2", @@ -125,7 +132,7 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "1.0.72", + "react-native-onyx": "1.0.76", "react-native-pager-view": "^6.2.0", "react-native-pdf": "^6.7.1", "react-native-performance": "^4.0.0", @@ -168,6 +175,8 @@ "@babel/runtime": "^7.20.0", "@electron/notarize": "^1.2.3", "@jest/globals": "^29.5.0", + "@kie/act-js": "^2.0.1", + "@kie/mock-github": "^1.0.0", "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", @@ -219,8 +228,8 @@ "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", - "electron": "^25.8.0", - "electron-builder": "24.5.0", + "electron": "^25.8.1", + "electron-builder": "24.6.4", "eslint": "^7.6.0", "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-expensify": "^2.0.38", @@ -261,7 +270,8 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.9.3", "webpack-font-preload-plugin": "^1.5.0", - "webpack-merge": "^5.8.0" + "webpack-merge": "^5.8.0", + "yaml": "^2.2.1" }, "overrides": { "react-native": "$react-native" diff --git a/src/App.js b/src/App.js index 7ec82b9a4f8a..284c6115d7b8 100644 --- a/src/App.js +++ b/src/App.js @@ -22,6 +22,7 @@ import ThemeProvider from './styles/themes/ThemeProvider'; import ThemeStylesProvider from './styles/ThemeStylesProvider'; import {CurrentReportIDContextProvider} from './components/withCurrentReportID'; import {EnvironmentProvider} from './components/withEnvironment'; +import {ReportAttachmentsProvider} from './pages/home/report/ReportAttachmentsContext'; import * as Session from './libs/actions/Session'; import useDefaultDragAndDrop from './hooks/useDefaultDragAndDrop'; import OnyxUpdateManager from './libs/actions/OnyxUpdateManager'; @@ -58,6 +59,7 @@ function App() { KeyboardStateProvider, PopoverContextProvider, CurrentReportIDContextProvider, + ReportAttachmentsProvider, PickerStateProvider, EnvironmentProvider, ThemeProvider, diff --git a/src/CONST.ts b/src/CONST.ts index cced7994711b..1ef2f3e83246 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4,6 +4,11 @@ import * as KeyCommand from 'react-native-key-command'; import * as Url from './libs/Url'; import SCREENS from './SCREENS'; +// Creating a default array and object this way because objects ({}) and arrays ([]) are not stable types. +// Freezing the array ensures that it cannot be unintentionally modified. +const EMPTY_ARRAY = Object.freeze([]); +const EMPTY_OBJECT = Object.freeze({}); + const CLOUDFRONT_DOMAIN = 'cloudfront.net'; const CLOUDFRONT_URL = `https://d2k5nsl2zxldvw.${CLOUDFRONT_DOMAIN}`; const ACTIVE_EXPENSIFY_URL = Url.addTrailingForwardSlash(Config?.NEW_EXPENSIFY_URL ?? 'https://new.expensify.com'); @@ -235,6 +240,8 @@ const CONST = { TASKS: 'tasks', THREADS: 'threads', CUSTOM_STATUS: 'customStatus', + NEW_DOT_CATEGORIES: 'newDotCategories', + NEW_DOT_TAGS: 'newDotTags', }, BUTTON_STATES: { DEFAULT: 'default', @@ -408,6 +415,8 @@ const CONST = { EXAMPLE_PHONE_NUMBER: '+15005550006', CONCIERGE_CHAT_NAME: 'Concierge', CLOUDFRONT_URL, + EMPTY_ARRAY, + EMPTY_OBJECT, USE_EXPENSIFY_URL, NEW_ZOOM_MEETING_URL: 'https://zoom.us/start/videomeeting', NEW_GOOGLE_MEET_MEETING_URL: 'https://meet.google.com/new', @@ -752,6 +761,10 @@ 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, + + WHITELISTED_TAGS: [/<>/, /< >/, /<->/, /<-->/, /
/, //], + PASSWORD_PAGE: { ERROR: { ALREADY_VALIDATED: 'Account already validated', @@ -878,8 +891,6 @@ const CONST = { QA: 'qa@expensify.com', QA_TRAVIS: 'qa+travisreceipts@expensify.com', RECEIPTS: 'receipts@expensify.com', - SAASTR: 'saastr@expensify.com', - SBE: 'sbe@expensify.com', STUDENT_AMBASSADOR: 'studentambassadors@expensify.com', SVFG: 'svfg@expensify.com', }, @@ -1080,6 +1091,29 @@ const CONST = { DEFAULT: 'en', }, + LANGUAGES: ['en', 'es'], + + PRONOUNS_LIST: [ + 'coCos', + 'eEyEmEir', + 'heHimHis', + 'heHimHisTheyThemTheirs', + 'sheHerHers', + 'sheHerHersTheyThemTheirs', + 'merMers', + 'neNirNirs', + 'neeNerNers', + 'perPers', + 'theyThemTheirs', + 'thonThons', + 'veVerVis', + 'viVir', + 'xeXemXyr', + 'zeZieZirHir', + 'zeHirHirs', + 'callMeByMyName', + ], + POLICY: { TYPE: { FREE: 'free', diff --git a/src/Expensify.js b/src/Expensify.js index 60ab9f756dff..1086bd32cff9 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -30,7 +30,6 @@ import KeyboardShortcutsModal from './components/KeyboardShortcutsModal'; import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper'; import EmojiPicker from './components/EmojiPicker/EmojiPicker'; import * as EmojiPickerAction from './libs/actions/EmojiPickerAction'; -import * as DemoActions from './libs/actions/DemoActions'; import DownloadAppModal from './components/DownloadAppModal'; import DeeplinkWrapper from './components/DeeplinkWrapper'; @@ -168,13 +167,11 @@ function Expensify(props) { // If the app is opened from a deep link, get the reportID (if exists) from the deep link and navigate to the chat report Linking.getInitialURL().then((url) => { - DemoActions.runDemoByURL(url); Report.openReportFromDeepLink(url, isAuthenticated); }); // Open chat report from a deep link (only mobile native) Linking.addEventListener('url', (state) => { - DemoActions.runDemoByURL(state.url); Report.openReportFromDeepLink(state.url, isAuthenticated); }); diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index b978f06dbfd9..2e0b75910bae 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -215,9 +215,6 @@ const ONYXKEYS = { // The last update ID that was applied to the client ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT: 'OnyxUpdatesLastUpdateIDAppliedToClient', - // Manual request tab selector - SELECTED_TAB: 'selectedTab', - // Receipt upload modal RECEIPT_MODAL: 'receiptModal', @@ -243,6 +240,8 @@ const ONYXKEYS = { POLICY_MEMBERS: 'policyMembers_', POLICY_CATEGORIES: 'policyCategories_', POLICY_RECENTLY_USED_CATEGORIES: 'policyRecentlyUsedCategories_', + POLICY_TAGS: 'policyTags_', + POLICY_RECENTLY_USED_TAGS: 'policyRecentlyUsedTags_', WORKSPACE_INVITE_MEMBERS_DRAFT: 'workspaceInviteMembersDraft_', REPORT: 'report_', REPORT_ACTIONS: 'reportActions_', @@ -255,6 +254,9 @@ const ONYXKEYS = { SECURITY_GROUP: 'securityGroup_', TRANSACTION: 'transactions_', + // Manual request tab selector + SELECTED_TAB: 'selectedTab_', + /** This is deprecated, but needed for a migration, so we still need to include it here so that it will be initialized in Onyx.init */ DEPRECATED_POLICY_MEMBER_LIST: 'policyMemberList_', }, @@ -364,7 +366,6 @@ type OnyxValues = { [ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID]: string; [ONYXKEYS.PREFERRED_THEME]: ValueOf; [ONYXKEYS.IS_USING_MEMORY_ONLY_KEYS]: boolean; - [ONYXKEYS.SELECTED_TAB]: string; [ONYXKEYS.RECEIPT_MODAL]: OnyxTypes.ReceiptModal; [ONYXKEYS.MAPBOX_ACCESS_TOKEN]: OnyxTypes.MapboxAccessToken; [ONYXKEYS.ONYX_UPDATES_FROM_SERVER]: OnyxTypes.OnyxUpdatesFromServer; @@ -376,7 +377,8 @@ type OnyxValues = { // Collections [ONYXKEYS.COLLECTION.DOWNLOAD]: OnyxTypes.Download; [ONYXKEYS.COLLECTION.POLICY]: OnyxTypes.Policy; - [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: unknown; + [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory; + [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTag; [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMember; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; [ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMember; @@ -391,6 +393,8 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: boolean; [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; + [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; + [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; // Forms [ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM]: OnyxTypes.AddDebitCardForm; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 3ea8bd868d6a..3bbdf4709cfc 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -98,6 +98,7 @@ export default { MONEY_REQUEST_CURRENCY: ':iouType/new/currency/:reportID?', MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?', MONEY_REQUEST_CATEGORY: ':iouType/new/category/:reportID?', + MONEY_REQUEST_TAG: ':iouType/new/tag/:reportID?', MONEY_REQUEST_MERCHANT: ':iouType/new/merchant/:reportID?', MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual', MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan', @@ -114,6 +115,10 @@ export default { getMoneyRequestCurrencyRoute: (iouType: string, reportID: string, currency: string, backTo: string) => `${iouType}/new/currency/${reportID}?currency=${currency}&backTo=${backTo}`, getMoneyRequestDescriptionRoute: (iouType: string, reportID = '') => `${iouType}/new/description/${reportID}`, getMoneyRequestCategoryRoute: (iouType: string, reportID = '') => `${iouType}/new/category/${reportID}`, + getMoneyRequestMerchantRoute: (iouType: string, reportID = '') => `${iouType}/new/merchant/${reportID}`, + getMoneyRequestDistanceTabRoute: (iouType: string, reportID = '') => `${iouType}/new/${reportID}/distance`, + getMoneyRequestWaypointRoute: (iouType: string, waypointIndex: number) => `${iouType}/new/waypoint/${waypointIndex}`, + getMoneyRequestTagRoute: (iouType: string, reportID = '') => `${iouType}/new/tag/${reportID}`, SPLIT_BILL_DETAILS: `r/:reportID/split/:reportActionID`, getSplitBillDetailsRoute: (reportID: string, reportActionID: string) => `r/${reportID}/split/${reportActionID}`, getNewTaskRoute: (reportID: string) => `${NEW_TASK}/${reportID}`, @@ -132,10 +137,10 @@ export default { FLAG_COMMENT: `flag/:reportID/:reportActionID`, getFlagCommentRoute: (reportID: string, reportActionID: string) => `flag/${reportID}/${reportActionID}`, SEARCH: 'search', - SAVE_THE_WORLD: 'save-the-world', - I_KNOW_A_TEACHER: 'save-the-world/i-know-a-teacher', - INTRO_SCHOOL_PRINCIPAL: 'save-the-world/intro-school-principal', - I_AM_A_TEACHER: 'save-the-world/i-am-a-teacher', + TEACHERS_UNITE: 'teachersunite', + I_KNOW_A_TEACHER: 'teachersunite/i-know-a-teacher', + INTRO_SCHOOL_PRINCIPAL: 'teachersunite/intro-school-principal', + I_AM_A_TEACHER: 'teachersunite/i-am-a-teacher', DETAILS: 'details', getDetailsRoute: (login: string) => `details?login=${encodeURIComponent(login)}`, PROFILE: 'a/:accountID', diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 70741f352089..71d331b68db0 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -2,6 +2,7 @@ import lodashGet from 'lodash/get'; import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import _ from 'lodash'; import CONST from '../CONST'; import Banner from './Banner'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; @@ -60,15 +61,25 @@ function ArchivedReportFooter(props) { oldDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(props.personalDetails, [oldAccountID, 'displayName']); } + const shouldRenderHTML = archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT; + + let policyName = ReportUtils.getPolicyName(props.report); + + if (shouldRenderHTML) { + oldDisplayName = _.escape(oldDisplayName); + displayName = _.escape(displayName); + policyName = _.escape(policyName); + } + return ( ${displayName}`, oldDisplayName: `${oldDisplayName}`, - policyName: `${ReportUtils.getPolicyName(props.report)}`, + policyName: `${policyName}`, })} - shouldRenderHTML={archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT} + shouldRenderHTML={shouldRenderHTML} shouldShowIcon /> ); diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index c07a4474a68b..d39906faf3a3 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -25,7 +25,6 @@ import HeaderGap from './HeaderGap'; import SafeAreaConsumer from './SafeAreaConsumer'; import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL'; import reportPropTypes from '../pages/reportPropTypes'; -import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot'; /** * Modal render prop component that exposes modal launching triggers that can be used @@ -351,7 +350,7 @@ function AttachmentModal(props) { onCanceled.current(), {once: true}); + fileInput.current.addEventListener( + 'cancel', + () => { + // For Android Chrome, the cancel event happens before the page is visible on physical devices, + // which makes it unreliable for us to show the keyboard, while on emulators it happens after the page is visible. + // So here we can delay calling the onCanceled.current function based on visibility in order to reliably show the keyboard. + if (Visibility.isVisible()) { + onCanceled.current(); + return; + } + const unsubscribeVisibilityListener = Visibility.onVisibilityChange(() => { + onCanceled.current(); + unsubscribeVisibilityListener(); + }); + }, + {once: true}, + ); }} accept={getAcceptableFileTypes(props.type)} /> diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js new file mode 100644 index 000000000000..3aeef8482e2d --- /dev/null +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -0,0 +1,115 @@ +import React, {useContext, useState} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import CONST from '../../../CONST'; +import styles from '../../../styles/styles'; +import useLocalize from '../../../hooks/useLocalize'; +import PressableWithoutFeedback from '../../Pressable/PressableWithoutFeedback'; +import Text from '../../Text'; +import Button from '../../Button'; +import AttachmentView from '../AttachmentView'; +import SafeAreaConsumer from '../../SafeAreaConsumer'; +import ReportAttachmentsContext from '../../../pages/home/report/ReportAttachmentsContext'; + +const propTypes = { + /** Attachment required information such as the source and file name */ + item: PropTypes.shape({ + /** Report action ID of the attachment */ + reportActionID: PropTypes.string, + + /** Whether source URL requires authentication */ + isAuthTokenRequired: PropTypes.bool, + + /** The source (URL) of the attachment */ + source: PropTypes.string, + + /** Additional information about the attachment file */ + file: PropTypes.shape({ + /** File name of the attachment */ + name: PropTypes.string, + }), + + /** Whether the attachment has been flagged */ + hasBeenFlagged: PropTypes.bool, + }).isRequired, + + /** Whether the attachment is currently being viewed in the carousel */ + isFocused: PropTypes.bool.isRequired, + + /** onPress callback */ + onPress: PropTypes.func, +}; + +const defaultProps = { + onPress: undefined, +}; + +function CarouselItem({item, isFocused, onPress}) { + const {translate} = useLocalize(); + const {isAttachmentHidden} = useContext(ReportAttachmentsContext); + // eslint-disable-next-line es/no-nullish-coalescing-operators + const [isHidden, setIsHidden] = useState(isAttachmentHidden(item.reportActionID) ?? item.hasBeenFlagged); + + const renderButton = (style) => ( + + ); + + if (isHidden) { + const children = ( + <> + {translate('moderation.flaggedContent')} + {renderButton([styles.mt2])} + + ); + return onPress ? ( + + {children} + + ) : ( + {children} + ); + } + + return ( + + + + + + {item.hasBeenFlagged && ( + + {({safeAreaPaddingBottomStyle}) => {renderButton([styles.m4, styles.alignSelfCenter])}} + + )} + + ); +} + +CarouselItem.propTypes = propTypes; +CarouselItem.defaultProps = defaultProps; + +export default CarouselItem; diff --git a/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js b/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js index b967d5ab0066..d5da25c89576 100644 --- a/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js +++ b/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js @@ -28,10 +28,12 @@ function extractAttachmentsFromReport(report, reportActions) { // By iterating actions in chronological order and prepending each attachment // we ensure correct order of attachments even across actions with multiple attachments. attachments.unshift({ + reportActionID: attribs['data-id'], source: tryResolveUrlFromApiRoot(expensifySource || attribs.src), isAuthTokenRequired: Boolean(expensifySource), file: {name: attribs[CONST.ATTACHMENT_ORIGINAL_FILENAME_ATTRIBUTE]}, isReceipt: false, + hasBeenFlagged: attribs['data-flagged'] === 'true', }); }, }); @@ -62,7 +64,10 @@ function extractAttachmentsFromReport(report, reportActions) { } } - htmlParser.write(_.get(action, ['message', 0, 'html'])); + const decision = _.get(action, ['message', 0, 'moderationDecision', 'decision'], ''); + const hasBeenFlagged = decision === CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE || decision === CONST.MODERATION.MODERATOR_DECISION_HIDDEN; + const html = _.get(action, ['message', 0, 'html'], '').replace('/>', `data-flagged="${hasBeenFlagged}" data-id="${action.reportActionID}"/>`); + htmlParser.write(html); }); htmlParser.end(); diff --git a/src/components/Attachments/AttachmentCarousel/index.js b/src/components/Attachments/AttachmentCarousel/index.js index 53c2c840d95d..5c731a0ccfee 100644 --- a/src/components/Attachments/AttachmentCarousel/index.js +++ b/src/components/Attachments/AttachmentCarousel/index.js @@ -2,10 +2,8 @@ import React, {useRef, useCallback, useState, useEffect} from 'react'; import {View, FlatList, PixelRatio, Keyboard} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import * as DeviceCapabilities from '../../../libs/DeviceCapabilities'; import styles from '../../../styles/styles'; import CarouselActions from './CarouselActions'; -import AttachmentView from '../AttachmentView'; import withWindowDimensions from '../../withWindowDimensions'; import CarouselButtons from './CarouselButtons'; import extractAttachmentsFromReport from './extractAttachmentsFromReport'; @@ -15,12 +13,13 @@ import withLocalize from '../../withLocalize'; import compose from '../../../libs/compose'; import useCarouselArrows from './useCarouselArrows'; import useWindowDimensions from '../../../hooks/useWindowDimensions'; +import CarouselItem from './CarouselItem'; import Navigation from '../../../libs/Navigation/Navigation'; import BlockingView from '../../BlockingViews/BlockingView'; import * as Illustrations from '../../Icon/Illustrations'; import variables from '../../../styles/variables'; +import * as DeviceCapabilities from '../../../libs/DeviceCapabilities'; -const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen(); const viewabilityConfig = { // To facilitate paging through the attachments, we want to consider an item "viewable" when it is // more than 95% visible. When that happens we update the page index in the state. @@ -31,6 +30,7 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, setDownl const scrollRef = useRef(null); const {windowWidth, isSmallScreenWidth} = useWindowDimensions(); + const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen(); const [containerWidth, setContainerWidth] = useState(0); const [page, setPage] = useState(0); @@ -99,7 +99,7 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, setDownl scrollRef.current.scrollToIndex({index: nextIndex, animated: canUseTouchScreen}); }, - [attachments, page], + [attachments, canUseTouchScreen, page], ); /** @@ -143,24 +143,23 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, setDownl /** * Defines how a single attachment should be rendered * @param {Object} item + * @param {String} item.reportActionID * @param {Boolean} item.isAuthTokenRequired * @param {String} item.source * @param {Object} item.file * @param {String} item.file.name + * @param {Boolean} item.hasBeenFlagged * @returns {JSX.Element} */ const renderItem = useCallback( ({item}) => ( - setShouldShowArrows(!shouldShowArrows) : undefined} - isUsedInCarousel /> ), - [activeSource, setShouldShowArrows, shouldShowArrows], + [activeSource, canUseTouchScreen, setShouldShowArrows, shouldShowArrows], ); return ( diff --git a/src/components/Attachments/AttachmentCarousel/index.native.js b/src/components/Attachments/AttachmentCarousel/index.native.js index 4162cfae88e9..95cda7c2f5c9 100644 --- a/src/components/Attachments/AttachmentCarousel/index.native.js +++ b/src/components/Attachments/AttachmentCarousel/index.native.js @@ -5,11 +5,11 @@ import _ from 'underscore'; import AttachmentCarouselPager from './Pager'; import styles from '../../../styles/styles'; import CarouselButtons from './CarouselButtons'; -import AttachmentView from '../AttachmentView'; import ONYXKEYS from '../../../ONYXKEYS'; import {propTypes, defaultProps} from './attachmentCarouselPropTypes'; import extractAttachmentsFromReport from './extractAttachmentsFromReport'; import useCarouselArrows from './useCarouselArrows'; +import CarouselItem from './CarouselItem'; import Navigation from '../../../libs/Navigation/Navigation'; import BlockingView from '../../BlockingViews/BlockingView'; import * as Illustrations from '../../Icon/Illustrations'; @@ -85,17 +85,14 @@ function AttachmentCarousel({report, reportActions, source, onNavigate, onClose, /** * Defines how a single attachment should be rendered - * @param {{ isAuthTokenRequired: Boolean, source: String, file: { name: String } }} item + * @param {{ reportActionID: String, isAuthTokenRequired: Boolean, source: String, file: { name: String }, hasBeenFlagged: Boolean }} item * @returns {JSX.Element} */ const renderItem = useCallback( ({item}) => ( - setShouldShowArrows(!shouldShowArrows)} /> ), diff --git a/src/components/Attachments/AttachmentCarousel/useCarouselArrows.js b/src/components/Attachments/AttachmentCarousel/useCarouselArrows.js index f43a26ab94ee..64c97fa99819 100644 --- a/src/components/Attachments/AttachmentCarousel/useCarouselArrows.js +++ b/src/components/Attachments/AttachmentCarousel/useCarouselArrows.js @@ -2,9 +2,8 @@ import {useCallback, useEffect, useRef, useState} from 'react'; import CONST from '../../../CONST'; import * as DeviceCapabilities from '../../../libs/DeviceCapabilities'; -const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen(); - function useCarouselArrows() { + const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen(); const [shouldShowArrows, setShouldShowArrowsInternal] = useState(canUseTouchScreen); const autoHideArrowTimeout = useRef(null); @@ -25,7 +24,7 @@ function useCarouselArrows() { autoHideArrowTimeout.current = setTimeout(() => { setShouldShowArrowsInternal(false); }, CONST.ARROW_HIDE_DELAY); - }, [cancelAutoHideArrows]); + }, [canUseTouchScreen, cancelAutoHideArrows]); const setShouldShowArrows = useCallback( (show = true) => { diff --git a/src/components/CategoryPicker/categoryPickerPropTypes.js b/src/components/CategoryPicker/categoryPickerPropTypes.js index ccc1643021ce..b8e24c199a73 100644 --- a/src/components/CategoryPicker/categoryPickerPropTypes.js +++ b/src/components/CategoryPicker/categoryPickerPropTypes.js @@ -14,11 +14,23 @@ const propTypes = { /* Onyx Props */ /** Collection of categories attached to a policy */ policyCategories: PropTypes.objectOf(categoryPropTypes), + + /* Onyx Props */ + /** Collection of recently used categories attached to a policy */ + policyRecentlyUsedCategories: PropTypes.arrayOf(PropTypes.string), + + /* Onyx Props */ + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + iou: PropTypes.shape({ + category: PropTypes.string.isRequired, + }), }; const defaultProps = { policyID: '', - policyCategories: null, + policyCategories: {}, + policyRecentlyUsedCategories: [], + iou: {}, }; export {propTypes, defaultProps}; diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index 163ab6673ca2..91c7e82e7887 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -1,47 +1,88 @@ -import React, {useMemo} from 'react'; -import _ from 'underscore'; +import React, {useMemo, useState} from 'react'; import {withOnyx} from 'react-native-onyx'; +import _ from 'underscore'; +import lodashGet from 'lodash/get'; import ONYXKEYS from '../../ONYXKEYS'; import {propTypes, defaultProps} from './categoryPickerPropTypes'; -import OptionsList from '../OptionsList'; import styles from '../../styles/styles'; -import ScreenWrapper from '../ScreenWrapper'; import Navigation from '../../libs/Navigation/Navigation'; import ROUTES from '../../ROUTES'; +import CONST from '../../CONST'; +import * as IOU from '../../libs/actions/IOU'; +import * as OptionsListUtils from '../../libs/OptionsListUtils'; +import OptionsSelector from '../OptionsSelector'; +import useLocalize from '../../hooks/useLocalize'; + +function CategoryPicker({policyCategories, reportID, iouType, iou, policyRecentlyUsedCategories}) { + const {translate} = useLocalize(); + const [searchValue, setSearchValue] = useState(''); + + const policyCategoriesCount = _.size(policyCategories); + const isCategoriesCountBelowThreshold = policyCategoriesCount < CONST.CATEGORY_LIST_THRESHOLD; -function CategoryPicker({policyCategories, reportID, iouType}) { - const sections = useMemo(() => { - const categoryList = _.chain(policyCategories) - .values() - .map((category) => ({ - text: category.name, - keyForList: category.name, - tooltipText: category.name, - })) - .value(); + const selectedOptions = useMemo(() => { + if (!iou.category) { + return []; + } return [ { - data: categoryList, + name: iou.category, + enabled: true, + accountID: null, }, ]; - }, [policyCategories]); + }, [iou.category]); + + const initialFocusedIndex = useMemo(() => { + if (isCategoriesCountBelowThreshold && selectedOptions.length > 0) { + return _.chain(policyCategories) + .values() + .findIndex((category) => category.name === selectedOptions[0].name, true) + .value(); + } + + return 0; + }, [policyCategories, selectedOptions, isCategoriesCountBelowThreshold]); + + const sections = useMemo( + () => OptionsListUtils.getNewChatOptions({}, {}, [], searchValue, selectedOptions, [], false, false, true, policyCategories, policyRecentlyUsedCategories, false).categoryOptions, + [policyCategories, policyRecentlyUsedCategories, searchValue, selectedOptions], + ); + + const headerMessage = OptionsListUtils.getHeaderMessage(lodashGet(sections, '[0].data.length', 0) > 0, false, searchValue); + const shouldShowTextInput = !isCategoriesCountBelowThreshold; const navigateBack = () => { Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); }; + const updateCategory = (category) => { + if (category.searchText === iou.category) { + IOU.resetMoneyRequestCategory(); + } else { + IOU.setMoneyRequestCategory(category.searchText); + } + + navigateBack(); + }; + return ( - - {({safeAreaPaddingBottomStyle}) => ( - - )} - + ); } @@ -53,4 +94,10 @@ export default withOnyx({ policyCategories: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, }, + policyRecentlyUsedCategories: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${policyID}`, + }, + iou: { + key: ONYXKEYS.IOU, + }, })(CategoryPicker); diff --git a/src/components/ConfirmedRoute.js b/src/components/ConfirmedRoute.js index aa7c38e0c535..6790e8ae4d65 100644 --- a/src/components/ConfirmedRoute.js +++ b/src/components/ConfirmedRoute.js @@ -8,6 +8,7 @@ import _ from 'underscore'; import ONYXKEYS from '../ONYXKEYS'; import CONST from '../CONST'; import * as MapboxToken from '../libs/actions/MapboxToken'; +import * as TransactionUtils from '../libs/TransactionUtils'; import * as Expensicons from './Icon/Expensicons'; import theme from '../styles/themes/default'; import styles from '../styles/styles'; @@ -47,7 +48,7 @@ const getWaypointMarkers = (waypoints) => { return; } - const index = Number(key.replace('waypoint', '')); + const index = TransactionUtils.getWaypointIndex(key); let MarkerComponent; if (index === 0) { MarkerComponent = Expensicons.DotIndicatorUnfilled; diff --git a/src/components/CountryPicker/CountrySelectorModal.js b/src/components/CountryPicker/CountrySelectorModal.js index 126cea7e842e..ac543d9921d2 100644 --- a/src/components/CountryPicker/CountrySelectorModal.js +++ b/src/components/CountryPicker/CountrySelectorModal.js @@ -49,13 +49,16 @@ function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySele const countries = useMemo( () => - _.map(translate('allCountries'), (countryName, countryISO) => ({ - value: countryISO, - keyForList: countryISO, - text: countryName, - isSelected: currentCountry === countryISO, - searchValue: StringUtils.sanitizeString(`${countryISO}${countryName}`), - })), + _.map(_.keys(CONST.ALL_COUNTRIES), (countryISO) => { + const countryName = translate(`allCountries.${countryISO}`); + return { + value: countryISO, + keyForList: countryISO, + text: countryName, + isSelected: currentCountry === countryISO, + searchValue: StringUtils.sanitizeString(`${countryISO}${countryName}`), + }; + }), [translate, currentCountry], ); @@ -87,7 +90,6 @@ function CountrySelectorModal({currentCountry, isVisible, onClose, onCountrySele sections={[{data: searchResults, indexOffset: 0}]} onSelectRow={onCountrySelected} onChangeText={setSearchValue} - shouldDelayFocus initiallyFocusedOptionKey={currentCountry} /> diff --git a/src/components/CountryPicker/index.js b/src/components/CountryPicker/index.js index c6bbae0dd645..c838ed8f4060 100644 --- a/src/components/CountryPicker/index.js +++ b/src/components/CountryPicker/index.js @@ -31,7 +31,6 @@ const defaultProps = { function CountryPicker({value, errorText, onInputChange, forwardedRef}) { const {translate} = useLocalize(); - const allCountries = translate('allCountries'); const [isPickerVisible, setIsPickerVisible] = useState(false); const [searchValue, setSearchValue] = useState(''); @@ -48,7 +47,7 @@ function CountryPicker({value, errorText, onInputChange, forwardedRef}) { hidePickerModal(); }; - const title = allCountries[value] || ''; + const title = value ? translate(`allCountries.${value}`) : ''; const descStyle = title.length === 0 ? styles.textNormal : null; return ( diff --git a/src/components/CustomStatusBar/index.js b/src/components/CustomStatusBar/index.js index 76752cb549e1..4848e6e35f59 100644 --- a/src/components/CustomStatusBar/index.js +++ b/src/components/CustomStatusBar/index.js @@ -1,11 +1,22 @@ import React, {useEffect} from 'react'; import StatusBar from '../../libs/StatusBar'; +import Navigation, {navigationRef} from '../../libs/Navigation/Navigation'; import themeColors from '../../styles/themes/default'; function CustomStatusBar() { useEffect(() => { - StatusBar.setBarStyle('light-content', true); - StatusBar.setBackgroundColor(themeColors.appBG); + Navigation.isNavigationReady().then(() => { + // Set the status bar colour depending on the current route. + // If we don't have any colour defined for a route, fall back to + // appBG color. + const currentRoute = navigationRef.getCurrentRoute(); + let currentScreenBackgroundColor = themeColors.appBG; + if (currentRoute && 'name' in currentRoute && currentRoute.name in themeColors.PAGE_BACKGROUND_COLORS) { + currentScreenBackgroundColor = themeColors.PAGE_BACKGROUND_COLORS[currentRoute.name]; + } + StatusBar.setBarStyle('light-content', true); + StatusBar.setBackgroundColor(currentScreenBackgroundColor); + }); }, []); return ; } diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js index c966cf62be96..9de98f365475 100644 --- a/src/components/DistanceRequest.js +++ b/src/components/DistanceRequest.js @@ -91,7 +91,7 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) const lastWaypointIndex = numberOfWaypoints - 1; const isLoadingRoute = lodashGet(transaction, 'comment.isLoading', false); - const hasRouteError = lodashHas(transaction, 'errorFields.route'); + const hasRouteError = !!lodashGet(transaction, 'errorFields.route'); const haveWaypointsChanged = !_.isEqual(previousWaypoints, waypoints); const doesRouteExist = lodashHas(transaction, 'routes.route0.geometry.coordinates'); const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints); @@ -104,7 +104,7 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) return; } - const index = Number(key.replace('waypoint', '')); + const index = TransactionUtils.getWaypointIndex(key); let MarkerComponent; if (index === 0) { MarkerComponent = Expensicons.DotIndicatorUnfilled; @@ -161,6 +161,13 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) Transaction.getRoute(iou.transactionID, validatedWaypoints); }, [shouldFetchRoute, iou.transactionID, validatedWaypoints, isOffline]); + useEffect(() => { + if (numberOfWaypoints <= numberOfPreviousWaypoints) { + return; + } + scrollViewRef.current.scrollToEnd({animated: true}); + }, [numberOfPreviousWaypoints, numberOfWaypoints]); + useEffect(updateGradientVisibility, [scrollContainerHeight, scrollContentHeight]); return ( @@ -170,19 +177,14 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) onLayout={(event = {}) => setScrollContainerHeight(lodashGet(event, 'nativeEvent.layout.height', 0))} > { - if (scrollContentHeight < height && numberOfWaypoints > numberOfPreviousWaypoints) { - scrollViewRef.current.scrollToEnd({animated: true}); - } - setScrollContentHeight(height); - }} + onContentSizeChange={(width, height) => setScrollContentHeight(height)} onScroll={updateGradientVisibility} scrollEventThrottle={variables.distanceScrollEventThrottle} ref={scrollViewRef} > {_.map(waypoints, (waypoint, key) => { // key is of the form waypoint0, waypoint1, ... - const index = Number(key.replace('waypoint', '')); + const index = TransactionUtils.getWaypointIndex(key); let descriptionKey = 'distance.waypointDescription.'; let waypointIcon; if (index === 0) { @@ -264,7 +266,7 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken}) success style={[styles.w100, styles.mb4, styles.ph4, styles.flexShrink0]} onPress={() => IOU.navigateToNextPage(iou, iouType, reportID, report)} - isDisabled={_.size(validatedWaypoints) < 2} + isDisabled={_.size(validatedWaypoints) < 2 || hasRouteError || isOffline} text={translate('common.next')} /> diff --git a/src/components/FocusTrapView/index.js b/src/components/FocusTrapView/index.js new file mode 100644 index 000000000000..2dcab7b9d998 --- /dev/null +++ b/src/components/FocusTrapView/index.js @@ -0,0 +1,75 @@ +/* + * The FocusTrap is only used on web and desktop + */ +import React, {useEffect, useRef} from 'react'; +import FocusTrap from 'focus-trap-react'; +import {View} from 'react-native'; +import {PropTypes} from 'prop-types'; +import {useIsFocused} from '@react-navigation/native'; + +const propTypes = { + /** Children to wrap with FocusTrap */ + children: PropTypes.node.isRequired, + + /** Whether to enable the FocusTrap */ + enabled: PropTypes.bool, + + /** + * Whether to disable auto focus + * It is used when the component inside the FocusTrap have their own auto focus logic + */ + shouldEnableAutoFocus: PropTypes.bool, +}; + +const defaultProps = { + enabled: true, + shouldEnableAutoFocus: false, +}; + +function FocusTrapView({enabled, shouldEnableAutoFocus, ...props}) { + const isFocused = useIsFocused(); + + /** + * Focus trap always needs a focusable element. + * In case that we don't have any focusable elements in the modal, + * the FocusTrap will use fallback View element using this ref. + */ + const ref = useRef(null); + + /** + * We have to set the 'tabindex' attribute to 0 to make the View focusable. + * Currently, it is not possible to set this through props. + * After the upgrade of 'react-native-web' to version 0.19 we can use 'tabIndex={0}' prop instead. + */ + useEffect(() => { + if (!ref.current) { + return; + } + ref.current.setAttribute('tabindex', '0'); + }, []); + + return enabled ? ( + shouldEnableAutoFocus && ref.current, + fallbackFocus: () => ref.current, + clickOutsideDeactivates: true, + }} + > + + + ) : ( + props.children + ); +} + +FocusTrapView.displayName = 'FocusTrapView'; +FocusTrapView.propTypes = propTypes; +FocusTrapView.defaultProps = defaultProps; + +export default FocusTrapView; diff --git a/src/components/FocusTrapView/index.native.js b/src/components/FocusTrapView/index.native.js new file mode 100644 index 000000000000..5720601f5a2b --- /dev/null +++ b/src/components/FocusTrapView/index.native.js @@ -0,0 +1,11 @@ +/* + * The FocusTrap is only used on web and desktop + */ + +function FocusTrapView({children}) { + return children; +} + +FocusTrapView.displayName = 'FocusTrapView'; + +export default FocusTrapView; diff --git a/src/components/Form.js b/src/components/Form.js index a45c6d769d57..ef6c3ea10474 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -113,12 +113,14 @@ function Form(props) { const {validate, onSubmit, children} = props; + const hasServerError = useMemo(() => Boolean(props.formState) && !_.isEmpty(props.formState.errors), [props.formState]); + /** * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} * @returns {Object} - An object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2} */ const onValidate = useCallback( - (values) => { + (values, shouldClearServerError = true) => { const trimmedStringValues = {}; _.each(values, (inputValue, inputID) => { if (_.isString(inputValue)) { @@ -128,7 +130,9 @@ function Form(props) { } }); - FormActions.setErrors(props.formID, null); + if (shouldClearServerError) { + FormActions.setErrors(props.formID, null); + } FormActions.setErrorFields(props.formID, null); // Run any validations passed as a prop @@ -136,8 +140,33 @@ function Form(props) { // Validate the input for html tags. It should supercede any other error _.each(trimmedStringValues, (inputValue, inputID) => { - // Return early if there is no value OR the value is not a string OR there are no HTML characters - if (!inputValue || !_.isString(inputValue) || inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX) === -1) { + // If the input value is empty OR is non-string, we don't need to validate it for HTML tags + if (!inputValue || !_.isString(inputValue)) { + return; + } + const foundHtmlTagIndex = inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX); + const leadingSpaceIndex = inputValue.search(CONST.VALIDATE_FOR_LEADINGSPACES_HTML_TAG_REGEX); + + // Return early if there are no HTML characters + if (leadingSpaceIndex === -1 && foundHtmlTagIndex === -1) { + return; + } + + const matchedHtmlTags = inputValue.match(CONST.VALIDATE_FOR_HTML_TAG_REGEX); + let isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(inputValue)); + // Check for any matches that the original regex (foundHtmlTagIndex) matched + if (matchedHtmlTags) { + // Check if any matched inputs does not match in WHITELISTED_TAGS list and return early if needed. + for (let i = 0; i < matchedHtmlTags.length; i++) { + const htmlTag = matchedHtmlTags[i]; + isMatch = _.some(CONST.WHITELISTED_TAGS, (r) => r.test(htmlTag)); + if (!isMatch) { + break; + } + } + } + + if (isMatch && leadingSpaceIndex === -1) { return; } @@ -321,7 +350,7 @@ function Form(props) { setTimeout(() => { setTouchedInput(inputID); if (props.shouldValidateOnBlur) { - onValidate(inputValues); + onValidate(inputValues, !hasServerError); } }, 200); } @@ -365,7 +394,19 @@ function Form(props) { return childrenElements; }, - [errors, inputRefs, inputValues, onValidate, props.draftValues, props.formID, props.formState, setTouchedInput, props.shouldValidateOnBlur, props.shouldValidateOnChange], + [ + errors, + inputRefs, + inputValues, + onValidate, + props.draftValues, + props.formID, + props.formState, + setTouchedInput, + props.shouldValidateOnBlur, + props.shouldValidateOnChange, + hasServerError, + ], ); const scrollViewContent = useCallback( diff --git a/src/components/FormAlertWithSubmitButton.js b/src/components/FormAlertWithSubmitButton.js index 9c941fa9b967..33d188719d11 100644 --- a/src/components/FormAlertWithSubmitButton.js +++ b/src/components/FormAlertWithSubmitButton.js @@ -46,6 +46,10 @@ const propTypes = { /** Custom content to display in the footer after submit button */ footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), + + /** Styles for the button */ + // eslint-disable-next-line react/forbid-prop-types + buttonStyles: PropTypes.arrayOf(PropTypes.object), }; const defaultProps = { @@ -59,10 +63,11 @@ const defaultProps = { disablePressOnEnter: false, isSubmitActionDangerous: false, footerContent: null, + buttonStyles: [], }; function FormAlertWithSubmitButton(props) { - const buttonMarginStyle = _.isEmpty(props.footerContent) ? {} : styles.mb3; + const buttonStyles = [_.isEmpty(props.footerContent) ? {} : styles.mb3, ...props.buttonStyles]; return ( ) : ( @@ -87,7 +92,7 @@ function FormAlertWithSubmitButton(props) { success pressOnEnter={!props.disablePressOnEnter} text={props.buttonText} - style={buttonMarginStyle} + style={buttonStyles} onPress={props.onSubmit} isDisabled={props.isDisabled} isLoading={props.isLoading} diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js index bfe39459ed74..74cf83a4a6f0 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.js @@ -1,4 +1,6 @@ -import React from 'react'; +import React, {memo} from 'react'; +import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import Navigation from '../../../libs/Navigation/Navigation'; import htmlRendererPropTypes from './htmlRendererPropTypes'; import styles from '../../../styles/styles'; @@ -8,12 +10,15 @@ import CONST from '../../../CONST'; import {ShowContextMenuContext, showContextMenuForReport} from '../../ShowContextMenuContext'; import tryResolveUrlFromApiRoot from '../../../libs/tryResolveUrlFromApiRoot'; import * as ReportUtils from '../../../libs/ReportUtils'; -import withLocalize, {withLocalizePropTypes} from '../../withLocalize'; import ROUTES from '../../../ROUTES'; +import ONYXKEYS from '../../../ONYXKEYS'; +import useLocalize from '../../../hooks/useLocalize'; -const propTypes = {...htmlRendererPropTypes, ...withLocalizePropTypes}; +const propTypes = {...htmlRendererPropTypes}; function ImageRenderer(props) { + const {translate} = useLocalize(); + const htmlAttribs = props.tnode.attributes; // There are two kinds of images that need to be displayed: @@ -72,7 +77,7 @@ function ImageRenderer(props) { ) } accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} - accessibilityLabel={props.translate('accessibilityHints.viewAttachment')} + accessibilityLabel={translate('accessibilityHints.viewAttachment')} > + lodashGet(prevProps, 'tnode.attributes') === lodashGet(nextProps, 'tnode.attributes') && + lodashGet(prevProps, 'user.shouldUseStagingServer') === lodashGet(nextProps, 'user.shouldUseStagingServer'), + ), +); diff --git a/src/components/Hoverable/index.js b/src/components/Hoverable/index.js index 35bbd4af7fd6..0b560703a069 100644 --- a/src/components/Hoverable/index.js +++ b/src/components/Hoverable/index.js @@ -13,6 +13,7 @@ class Hoverable extends Component { super(props); this.handleVisibilityChange = this.handleVisibilityChange.bind(this); + this.checkHover = this.checkHover.bind(this); this.state = { isHovered: false, @@ -23,6 +24,7 @@ class Hoverable extends Component { componentDidMount() { document.addEventListener('visibilitychange', this.handleVisibilityChange); + document.addEventListener('mouseover', this.checkHover); } componentDidUpdate(prevProps) { @@ -37,6 +39,7 @@ class Hoverable extends Component { componentWillUnmount() { document.removeEventListener('visibilitychange', this.handleVisibilityChange); + document.removeEventListener('mouseover', this.checkHover); } /** @@ -54,6 +57,24 @@ class Hoverable extends Component { } } + /** + * Checks the hover state of a component and updates it based on the event target. + * This is necessary to handle cases where the hover state might get stuck due to an unreliable mouseleave trigger, + * such as when an element is removed before the mouseleave event is triggered. + * @param {Event} e - The hover event object. + */ + checkHover(e) { + if (!this.wrapperView || !this.state.isHovered) { + return; + } + + if (this.wrapperView.contains(e.target)) { + return; + } + + this.setIsHovered(false); + } + handleVisibilityChange() { if (document.visibilityState !== 'hidden') { return; diff --git a/src/components/IllustratedHeaderPageLayout.js b/src/components/IllustratedHeaderPageLayout.js index d1403bd4029e..be4cb12d935e 100644 --- a/src/components/IllustratedHeaderPageLayout.js +++ b/src/components/IllustratedHeaderPageLayout.js @@ -27,14 +27,18 @@ const propTypes = { /** A fixed footer to display at the bottom of the page. */ footer: PropTypes.node, + + /** Overlay content to display on top of animation */ + overlayContent: PropTypes.func, }; const defaultProps = { backgroundColor: themeColors.appBG, footer: null, + overlayContent: null, }; -function IllustratedHeaderPageLayout({backgroundColor, children, illustration, footer, ...propsToPassToHeader}) { +function IllustratedHeaderPageLayout({backgroundColor, children, illustration, footer, overlayContent, ...propsToPassToHeader}) { const {windowHeight} = useWindowDimensions(); const {isOffline} = useNetwork(); return ( @@ -65,6 +69,7 @@ function IllustratedHeaderPageLayout({backgroundColor, children, illustration, f autoPlay loop /> + {overlayContent && overlayContent()} {children} diff --git a/src/components/Image/imagePropTypes.js b/src/components/Image/imagePropTypes.js index 46ec83384d62..c02e48eef659 100644 --- a/src/components/Image/imagePropTypes.js +++ b/src/components/Image/imagePropTypes.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import stylePropTypes from '../../styles/stylePropTypes'; +import sourcePropTypes from './sourcePropTypes'; import RESIZE_MODES from './resizeModes'; const imagePropTypes = { @@ -7,14 +8,7 @@ const imagePropTypes = { style: stylePropTypes, /** The static asset or URI source of the image */ - source: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.shape({ - uri: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - // eslint-disable-next-line react/forbid-prop-types - headers: PropTypes.object, - }), - ]).isRequired, + source: sourcePropTypes.isRequired, /** Should an auth token be included in the image request */ isAuthTokenRequired: PropTypes.bool, diff --git a/src/components/Image/sourcePropTypes/index.js b/src/components/Image/sourcePropTypes/index.js new file mode 100644 index 000000000000..99e88b5cf343 --- /dev/null +++ b/src/components/Image/sourcePropTypes/index.js @@ -0,0 +1,11 @@ +import PropTypes from 'prop-types'; + +export default PropTypes.oneOfType([ + PropTypes.number, + PropTypes.shape({ + uri: PropTypes.string.isRequired, + // eslint-disable-next-line react/forbid-prop-types + headers: PropTypes.object, + }), + PropTypes.string, +]); diff --git a/src/components/Image/sourcePropTypes/index.native.js b/src/components/Image/sourcePropTypes/index.native.js new file mode 100644 index 000000000000..629b21852613 --- /dev/null +++ b/src/components/Image/sourcePropTypes/index.native.js @@ -0,0 +1,10 @@ +import PropTypes from 'prop-types'; + +export default PropTypes.oneOfType([ + PropTypes.number, + PropTypes.shape({ + uri: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + // eslint-disable-next-line react/forbid-prop-types + headers: PropTypes.object, + }), +]); diff --git a/src/components/KeyboardShortcutsModal.js b/src/components/KeyboardShortcutsModal.js index 9d78a22b5aa8..6ca3cce6412c 100644 --- a/src/components/KeyboardShortcutsModal.js +++ b/src/components/KeyboardShortcutsModal.js @@ -1,4 +1,4 @@ -import React, {useEffect, useRef} from 'react'; +import React, {useEffect, useRef, useState} from 'react'; import PropTypes from 'prop-types'; import {View, ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; @@ -41,7 +41,7 @@ const openShortcutModalConfig = CONST.KEYBOARD_SHORTCUTS.SHORTCUT_MODAL; function KeyboardShortcutsModal({isShortcutsModalOpen = false, isSmallScreenWidth, translate}) { const subscribedOpenModalShortcuts = useRef([]); const modalType = isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE; - const shortcuts = KeyboardShortcut.getDocumentedShortcuts(); + const [shortcuts, setShortcurts] = useState([]); /* * Subscribe shortcuts that only are used when the modal is open @@ -79,6 +79,7 @@ function KeyboardShortcutsModal({isShortcutsModalOpen = false, isSmallScreenWidt KeyboardShortcut.subscribe(arrowUpConfig.shortcutKey, () => {}, arrowUpConfig.descriptionKey, arrowUpConfig.modifiers, true), KeyboardShortcut.subscribe(arrowDownConfig.shortcutKey, () => {}, arrowDownConfig.descriptionKey, arrowDownConfig.modifiers, true), ]; + setShortcurts(KeyboardShortcut.getDocumentedShortcuts()); }; /* diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 95b1fc0f801e..75be8c67fbf1 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -121,7 +121,8 @@ function OptionRowLHN(props) { '', popoverAnchor, props.reportID, - {}, + '0', + props.reportID, '', () => {}, () => setIsContextMenuActive(false), @@ -256,10 +257,12 @@ function OptionRowLHN(props) { accessible={false} > {shouldShowGreenDotIndicator && ( - + + + )} {optionItem.hasDraftComment && optionItem.isAllowedToComment && ( { if (!optionItem || optionItem.hasDraftComment || !comment || comment.length <= 0 || isFocused) { @@ -189,20 +194,26 @@ export default React.memo( preferredLocale: { key: ONYXKEYS.NVP_PREFERRED_LOCALE, }, - policies: { - key: ONYXKEYS.COLLECTION.POLICY, - }, }), withOnyx({ parentReportActions: { key: ({fullReport}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${fullReport.parentReportID}`, canEvict: false, }, + policy: { + key: ({fullReport}) => `${ONYXKEYS.COLLECTION.POLICY}${fullReport.policyID}`, + }, // Ideally, we aim to access only the last transaction for the current report by listening to changes in reportActions. // In some scenarios, a transaction might be created after reportActions have been modified. // This can lead to situations where `lastTransaction` doesn't update and retains the previous value. // However, performance overhead of this is minimized by using memos inside the component. receiptTransactions: {key: ONYXKEYS.COLLECTION.TRANSACTION}, }), + withOnyx({ + transaction: { + key: ({fullReport, parentReportActions}) => + `${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(parentReportActions, [fullReport.parentReportActionID, 'originalMessage', 'IOUTransactionID'], '')}`, + }, + }), )(OptionRowLHNData), ); diff --git a/src/components/LocalePicker.js b/src/components/LocalePicker.js index 532c29535e50..435f88e51e53 100644 --- a/src/components/LocalePicker.js +++ b/src/components/LocalePicker.js @@ -27,9 +27,11 @@ const defaultProps = { }; function LocalePicker(props) { - const localesToLanguages = _.map(props.translate('languagePage.languages'), (language, key) => ({ - value: key, - label: language.label, + const localesToLanguages = _.map(CONST.LANGUAGES, (language) => ({ + value: language, + label: props.translate(`languagePage.languages.${language}.label`), + keyForList: language, + isSelected: props.preferredLocale === language, })); return ( (({accessToken, style, ma styleURL={styleURL} onMapIdle={setMapIdle} pitchEnabled={pitchEnabled} + attributionPosition={{...styles.r2, ...styles.b2}} + logoPosition={{...styles.l2, ...styles.b2}} // eslint-disable-next-line {...responder.panHandlers} > diff --git a/src/components/MoneyReportHeader.js b/src/components/MoneyReportHeader.js index 7e6cc78ebd13..06a7f0b57b8e 100644 --- a/src/components/MoneyReportHeader.js +++ b/src/components/MoneyReportHeader.js @@ -69,8 +69,8 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, report const isManager = ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(session, 'accountID', null) === moneyRequestReport.managerID; const isPayer = policyType === CONST.POLICY.TYPE.CORPORATE ? isPolicyAdmin && isApproved : isPolicyAdmin || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && isManager); const shouldShowSettlementButton = useMemo( - () => isPayer && !isSettled && !moneyRequestReport.isWaitingOnBankAccount && reportTotal !== 0, - [isPayer, isSettled, moneyRequestReport, reportTotal], + () => isPayer && !isSettled && !moneyRequestReport.isWaitingOnBankAccount && reportTotal !== 0 && !ReportUtils.isArchivedRoom(chatReport), + [isPayer, isSettled, moneyRequestReport, reportTotal, chatReport], ); const shouldShowApproveButton = useMemo(() => { if (policyType !== CONST.POLICY.TYPE.CORPORATE) { diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index a7695c939907..966f5f4340a7 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -8,6 +8,7 @@ import lodashGet from 'lodash/get'; import styles from '../styles/styles'; import * as ReportUtils from '../libs/ReportUtils'; import * as OptionsListUtils from '../libs/OptionsListUtils'; +import Permissions from '../libs/Permissions'; import OptionsSelector from './OptionsSelector'; import ONYXKEYS from '../ONYXKEYS'; import compose from '../libs/compose'; @@ -29,6 +30,7 @@ import Image from './Image'; import useLocalize from '../hooks/useLocalize'; import * as ReceiptUtils from '../libs/ReceiptUtils'; import categoryPropTypes from './categoryPropTypes'; +import tagPropTypes from './tagPropTypes'; import ConfirmedRoute from './ConfirmedRoute'; import transactionPropTypes from './transactionPropTypes'; import DistanceRequestUtils from '../libs/DistanceRequestUtils'; @@ -68,6 +70,9 @@ const propTypes = { /** IOU Category */ iouCategory: PropTypes.string, + /** IOU Tag */ + iouTag: PropTypes.string, + /** Selected participants from MoneyRequestModal with login / accountID */ selectedParticipants: PropTypes.arrayOf(optionPropTypes).isRequired, @@ -90,6 +95,9 @@ const propTypes = { email: PropTypes.string.isRequired, }), + /** List of betas available to current user */ + betas: PropTypes.arrayOf(PropTypes.string), + /** The policyID of the request */ policyID: PropTypes.string, @@ -105,10 +113,6 @@ const propTypes = { /** List styles for OptionsSelector */ listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), - /* Onyx Props */ - /** Collection of categories attached to a policy */ - policyCategories: PropTypes.objectOf(categoryPropTypes), - /** ID of the transaction that represents the money request */ transactionID: PropTypes.string, @@ -129,6 +133,19 @@ const propTypes = { /** Whether the money request is a distance request */ isDistanceRequest: PropTypes.bool, + + /* Onyx Props */ + /** Collection of categories attached to a policy */ + policyCategories: PropTypes.objectOf(categoryPropTypes), + + /** Collection of tags attached to a policy */ + policyTags: PropTypes.objectOf( + PropTypes.shape({ + name: PropTypes.string, + required: PropTypes.bool, + tags: PropTypes.objectOf(tagPropTypes), + }), + ), }; const defaultProps = { @@ -137,6 +154,7 @@ const defaultProps = { onSelectParticipant: () => {}, iouType: CONST.IOU.MONEY_REQUEST_TYPE.REQUEST, iouCategory: '', + iouTag: '', payeePersonalDetails: null, canModifyParticipants: false, isReadOnly: false, @@ -144,6 +162,7 @@ const defaultProps = { session: { email: null, }, + betas: [], policyID: '', reportID: '', ...withCurrentUserPersonalDetailsDefaultProps, @@ -151,6 +170,7 @@ const defaultProps = { receiptSource: '', listStyles: [], policyCategories: {}, + policyTags: {}, transactionID: '', transaction: {}, mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, @@ -171,7 +191,13 @@ function MoneyRequestConfirmationList(props) { const {unit, rate, currency} = props.mileageRate; const distance = lodashGet(transaction, 'routes.route0.distance', 0); const shouldCalculateDistanceAmount = props.isDistanceRequest && props.iouAmount === 0; - const shouldCategoryEditable = !_.isEmpty(props.policyCategories) && !props.isDistanceRequest; + const shouldCategoryBeEditable = !_.isEmpty(props.policyCategories) && Permissions.canUseCategories(props.betas); + + // Fetches the first tag list of the policy + const tagListKey = _.first(_.keys(props.policyTags)); + const tagList = lodashGet(props.policyTags, [tagListKey, 'tags'], []); + const tagListName = lodashGet(props.policyTags, [tagListKey, 'name'], ''); + const canUseTags = Permissions.canUseTags(props.betas); const formattedAmount = CurrencyUtils.convertToDisplayString( shouldCalculateDistanceAmount ? DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate) : props.iouAmount, @@ -484,7 +510,7 @@ function MoneyRequestConfirmationList(props) { disabled={didConfirm || props.isReadOnly || !isTypeRequest} /> )} - {shouldCategoryEditable && ( + {shouldCategoryBeEditable && ( )} + {canUseTags && !!tagList && ( + Navigation.navigate(ROUTES.getMoneyRequestTagRoute(props.iouType, props.reportID))} + style={[styles.moneyRequestMenuItem, styles.mb2]} + disabled={didConfirm || props.isReadOnly} + /> + )} )} @@ -509,9 +545,15 @@ export default compose( session: { key: ONYXKEYS.SESSION, }, + betas: { + key: ONYXKEYS.BETAS, + }, policyCategories: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, }, + policyTags: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + }, mileageRate: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, selector: DistanceRequestUtils.getDefaultMileageRate, diff --git a/src/components/MoneyRequestHeader.js b/src/components/MoneyRequestHeader.js index f04a41ae1153..bdd7365b7893 100644 --- a/src/components/MoneyRequestHeader.js +++ b/src/components/MoneyRequestHeader.js @@ -15,19 +15,16 @@ import Navigation from '../libs/Navigation/Navigation'; import ROUTES from '../ROUTES'; import ONYXKEYS from '../ONYXKEYS'; import * as IOU from '../libs/actions/IOU'; -import * as ReportActionsUtils from '../libs/ReportActionsUtils'; import ConfirmModal from './ConfirmModal'; import useLocalize from '../hooks/useLocalize'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; import * as TransactionUtils from '../libs/TransactionUtils'; +import reportActionPropTypes from '../pages/home/report/reportActionPropTypes'; const propTypes = { /** The report currently being looked at */ report: iouReportPropTypes.isRequired, - /** The expense report or iou report (only will have a value if this is a transaction thread) */ - parentReport: iouReportPropTypes, - /** The policy which the report is tied to */ policy: PropTypes.shape({ /** Name of the policy */ @@ -37,12 +34,25 @@ const propTypes = { /** Personal details so we can get the ones for the report participants */ personalDetails: PropTypes.objectOf(participantPropTypes).isRequired, + /** Onyx Props */ /** Session info for the currently logged in user. */ session: PropTypes.shape({ /** Currently logged in user email */ email: PropTypes.string, }), + /** The expense report or iou report (only will have a value if this is a transaction thread) */ + parentReport: iouReportPropTypes, + + /** The report action the transaction is tied to from the parent report */ + parentReportAction: PropTypes.shape(reportActionPropTypes), + + /** The transaction from the parent report action */ + transaction: PropTypes.shape({ + /** The ID of the transaction */ + transactionID: PropTypes.string, + }), + ...windowDimensionsPropTypes, }; @@ -51,6 +61,8 @@ const defaultProps = { email: null, }, parentReport: {}, + parentReportAction: {}, + transaction: {}, }; function MoneyRequestHeader(props) { @@ -59,21 +71,18 @@ function MoneyRequestHeader(props) { const moneyRequestReport = props.parentReport; const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); - // Only the requestor can take delete the request, admins can only edit it. - const isActionOwner = parentReportAction.actorAccountID === lodashGet(props.session, 'accountID', null); + const isActionOwner = props.parentReportAction.actorAccountID === lodashGet(props.session, 'accountID', null); const report = props.report; report.ownerAccountID = lodashGet(props, ['parentReport', 'ownerAccountID'], null); report.ownerEmail = lodashGet(props, ['parentReport', 'ownerEmail'], ''); const deleteTransaction = useCallback(() => { - IOU.deleteMoneyRequest(parentReportAction.originalMessage.IOUTransactionID, parentReportAction, true); + IOU.deleteMoneyRequest(props.parentReportAction.originalMessage.IOUTransactionID, props.parentReportAction, true); setIsDeleteModalVisible(false); - }, [parentReportAction, setIsDeleteModalVisible]); + }, [props.parentReportAction, setIsDeleteModalVisible]); - const transaction = TransactionUtils.getLinkedTransaction(parentReportAction); - const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); + const isScanning = TransactionUtils.hasReceipt(props.transaction) && TransactionUtils.isReceiptBeingScanned(props.transaction); return ( <> @@ -85,7 +94,7 @@ function MoneyRequestHeader(props) { threeDotsMenuItems={[ { icon: Expensicons.Trashcan, - text: translate('reportActionContextMenu.deleteAction', {action: parentReportAction}), + text: translate('reportActionContextMenu.deleteAction', {action: props.parentReportAction}), onSelected: () => setIsDeleteModalVisible(true), }, ]} @@ -125,5 +134,14 @@ export default compose( parentReport: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, }, + parentReportAction: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${(report.parentReportID, report.parentReportActionID)}`, + selector: (reportActions, props) => props && props.parentReport && reportActions && reportActions[props.parentReport.parentReportActionID], + canEvict: false, + }, + transaction: { + key: ({report, parentReportActions}) => + `${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(parentReportActions, [report.parentReportActionID, 'originalMessage', 'IOUTransactionID'], '')}`, + }, }), )(MoneyRequestHeader); diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js index 2f99b21b6523..fb0411d24f4c 100644 --- a/src/components/OfflineWithFeedback.js +++ b/src/components/OfflineWithFeedback.js @@ -37,6 +37,9 @@ const propTypes = { /** Whether we should show the error messages */ shouldShowErrorMessages: PropTypes.bool, + /** Whether we should disable opacity */ + shouldDisableOpacity: PropTypes.bool, + /** A function to run when the X button next to the error is clicked */ onClose: PropTypes.func, @@ -63,6 +66,7 @@ const defaultProps = { shouldHideOnDelete: true, errors: null, shouldShowErrorMessages: true, + shouldDisableOpacity: false, onClose: () => {}, style: [], contentContainerStyle: [], @@ -96,7 +100,7 @@ function OfflineWithFeedback(props) { const isOfflinePendingAction = props.network.isOffline && props.pendingAction; const isUpdateOrDeleteError = hasErrors && (props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); const isAddError = hasErrors && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD; - const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError; + const needsOpacity = !props.shouldDisableOpacity && ((isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError); const needsStrikeThrough = props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; const hideChildren = props.shouldHideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; let children = props.children; diff --git a/src/components/Onfido/index.css b/src/components/Onfido/index.css index 7e05cce7d49d..5c76f42037a5 100644 --- a/src/components/Onfido/index.css +++ b/src/components/Onfido/index.css @@ -46,4 +46,11 @@ spacing makes room for the header without cutting off the bottom of the Onfido window. */ height: 92% !important; } -} + + /* + * Solves issue with height not working for `onfido-sdk-ui-Modal-inner` container when device width is in between 490 - 600pixels. + */ + #onfido-mount { + height: 100%; + } +} \ No newline at end of file diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index adaa4457bbd9..50aff23dc9d0 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -39,6 +39,9 @@ const propTypes = { /** Whether we should show the selected state */ showSelectedState: PropTypes.bool, + /** Whether we highlight selected option */ + highlightSelected: PropTypes.bool, + /** Whether this item is selected */ isSelected: PropTypes.bool, @@ -57,6 +60,9 @@ const propTypes = { /** Whether to remove the lateral padding and align the content with the margins */ shouldDisableRowInnerPadding: PropTypes.bool, + /** Whether to wrap large text up to 2 lines */ + isMultilineSupported: PropTypes.bool, + style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), ...withLocalizePropTypes, @@ -65,12 +71,14 @@ const propTypes = { const defaultProps = { hoverStyle: styles.sidebarLinkHover, showSelectedState: false, + highlightSelected: false, isSelected: false, boldStyle: false, showTitleTooltip: false, onSelectRow: undefined, isDisabled: false, optionIsFocused: false, + isMultilineSupported: false, style: null, shouldHaveOptionSeparator: false, shouldDisableRowInnerPadding: false, @@ -89,9 +97,11 @@ class OptionRow extends Component { return ( this.state.isDisabled !== nextState.isDisabled || this.props.isDisabled !== nextProps.isDisabled || + this.props.isMultilineSupported !== nextProps.isMultilineSupported || this.props.isSelected !== nextProps.isSelected || this.props.shouldHaveOptionSeparator !== nextProps.shouldHaveOptionSeparator || this.props.showSelectedState !== nextProps.showSelectedState || + this.props.highlightSelected !== nextProps.highlightSelected || this.props.showTitleTooltip !== nextProps.showTitleTooltip || !_.isEqual(this.props.option.icons, nextProps.option.icons) || this.props.optionIsFocused !== nextProps.optionIsFocused || @@ -119,7 +129,7 @@ class OptionRow extends Component { let pressableRef = null; const textStyle = this.props.optionIsFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText; const textUnreadStyle = this.props.boldStyle || this.props.option.boldStyle ? [textStyle, styles.sidebarLinkTextBold] : [textStyle]; - const displayNameStyle = StyleUtils.combineStyles(styles.optionDisplayName, textUnreadStyle, this.props.style, styles.pre); + const displayNameStyle = StyleUtils.combineStyles(styles.optionDisplayName, textUnreadStyle, this.props.style, styles.pre, this.state.isDisabled ? styles.optionRowDisabled : {}); const alternateTextStyle = StyleUtils.combineStyles( textStyle, styles.optionAlternateText, @@ -182,6 +192,7 @@ class OptionRow extends Component { this.props.optionIsFocused ? styles.sidebarLinkActive : null, this.props.shouldHaveOptionSeparator && styles.borderTop, !this.props.onSelectRow && !this.props.isDisabled ? styles.cursorDefault : null, + this.props.isSelected && this.props.highlightSelected && styles.optionRowSelected, ]} accessibilityLabel={this.props.option.text} accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} @@ -216,7 +227,7 @@ class OptionRow extends Component { fullTitle={this.props.option.text} displayNamesWithTooltips={displayNamesWithTooltips} tooltipEnabled={this.props.showTitleTooltip} - numberOfLines={1} + numberOfLines={this.props.isMultilineSupported ? 2 : 1} textStyles={displayNameStyle} shouldUseFullTitle={ this.props.option.isChatRoom || @@ -249,6 +260,14 @@ class OptionRow extends Component { )} {this.props.showSelectedState && } + {this.props.isSelected && this.props.highlightSelected && ( + + + + )} {Boolean(this.props.option.customIcon) && ( diff --git a/src/components/OptionsList/BaseOptionsList.js b/src/components/OptionsList/BaseOptionsList.js index 8f63cfc29959..47efa1a5ac9e 100644 --- a/src/components/OptionsList/BaseOptionsList.js +++ b/src/components/OptionsList/BaseOptionsList.js @@ -56,10 +56,12 @@ function BaseOptionsList({ shouldDisableRowInnerPadding, disableFocusOptions, canSelectMultipleOptions, + highlightSelectedOptions, onSelectRow, boldStyle, isDisabled, innerRef, + isRowMultilineSupported, }) { const flattenedData = useRef(); const previousSections = usePrevious(sections); @@ -168,6 +170,18 @@ function BaseOptionsList({ */ const renderItem = ({item, index, section}) => { const isItemDisabled = isDisabled || section.isDisabled || !!item.isDisabled; + const isSelected = _.some(selectedOptions, (option) => { + if (option.accountID === item.accountID) { + return true; + } + + if (_.isEmpty(option.name)) { + return false; + } + + return option.name === item.searchText; + }); + return ( option.accountID === item.accountID))} + isSelected={isSelected} showSelectedState={canSelectMultipleOptions} + highlightSelected={highlightSelectedOptions} boldStyle={boldStyle} isDisabled={isItemDisabled} shouldHaveOptionSeparator={index > 0 && shouldHaveOptionSeparator} shouldDisableRowInnerPadding={shouldDisableRowInnerPadding} + isMultilineSupported={isRowMultilineSupported} /> ); }; diff --git a/src/components/OptionsList/optionsListPropTypes.js b/src/components/OptionsList/optionsListPropTypes.js index 74c13c7f2455..a2479c878041 100644 --- a/src/components/OptionsList/optionsListPropTypes.js +++ b/src/components/OptionsList/optionsListPropTypes.js @@ -40,6 +40,9 @@ const propTypes = { /** Whether we can select multiple options or not */ canSelectMultipleOptions: PropTypes.bool, + /** Whether we highlight selected options */ + highlightSelectedOptions: PropTypes.bool, + /** Whether to show headers above each section or not */ hideSectionHeaders: PropTypes.bool, @@ -78,6 +81,9 @@ const propTypes = { /** Whether to show the scroll bar */ showScrollIndicator: PropTypes.bool, + + /** Whether to wrap large text up to 2 lines */ + isRowMultilineSupported: PropTypes.bool, }; const defaultProps = { @@ -88,6 +94,7 @@ const defaultProps = { focusedIndex: 0, selectedOptions: [], canSelectMultipleOptions: false, + highlightSelectedOptions: false, hideSectionHeaders: false, disableFocusOptions: false, boldStyle: false, @@ -101,6 +108,7 @@ const defaultProps = { shouldHaveOptionSeparator: false, shouldDisableRowInnerPadding: false, showScrollIndicator: false, + isRowMultilineSupported: false, }; export {propTypes, defaultProps}; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 4e4a519ac621..ee3840bff69d 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -139,6 +139,10 @@ class BaseOptionsSelector extends Component { * @returns {Number} */ getInitiallyFocusedIndex(allOptions) { + if (_.isNumber(this.props.initialFocusedIndex)) { + return this.props.initialFocusedIndex; + } + if (this.props.selectedOptions.length > 0) { return this.props.selectedOptions.length; } @@ -224,6 +228,14 @@ class BaseOptionsSelector extends Component { } } + focus() { + if (!this.textInput) { + return; + } + + this.textInput.focus(); + } + /** * Flattens the sections into a single array of options. * Each object in this array is enhanced to have: @@ -366,6 +378,7 @@ class BaseOptionsSelector extends Component { showTitleTooltip={this.props.showTitleTooltip} isDisabled={this.props.isDisabled} shouldHaveOptionSeparator={this.props.shouldHaveOptionSeparator} + highlightSelectedOptions={this.props.highlightSelectedOptions} onLayout={() => { if (this.props.selectedOptions.length === 0) { this.scrollToIndex(this.state.focusedIndex, false); @@ -380,6 +393,7 @@ class BaseOptionsSelector extends Component { listStyles={this.props.listStyles} isLoading={!this.props.shouldShowOptions} showScrollIndicator={this.props.showScrollIndicator} + isRowMultilineSupported={this.props.isRowMultilineSupported} /> ); return ( diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 02b807bf66c1..dff0a16c0b3e 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -53,6 +53,9 @@ const propTypes = { /** Whether we can select multiple options */ canSelectMultipleOptions: PropTypes.bool, + /** Whether we highlight selected options */ + highlightSelectedOptions: PropTypes.bool, + /** Whether any section headers should be visible */ hideSectionHeaders: PropTypes.bool, @@ -106,6 +109,12 @@ const propTypes = { /** Whether to use default padding and flex styles for children */ shouldUseStyleForChildren: PropTypes.bool, + + /** Whether to wrap large text up to 2 lines */ + isRowMultilineSupported: PropTypes.bool, + + /** Initial focused index value */ + initialFocusedIndex: PropTypes.number, }; const defaultProps = { @@ -116,6 +125,7 @@ const defaultProps = { selectedOptions: [], headerMessage: '', canSelectMultipleOptions: false, + highlightSelectedOptions: false, hideSectionHeaders: false, boldStyle: false, showTitleTooltip: false, @@ -136,6 +146,8 @@ const defaultProps = { shouldShowTextInput: true, onChangeText: () => {}, shouldUseStyleForChildren: true, + isRowMultilineSupported: false, + initialFocusedIndex: undefined, }; export {propTypes, defaultProps}; diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index c240ade664e5..0bd9936c628b 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -148,6 +148,7 @@ class PDFView extends Component { )} {this.state.shouldAttemptPDFLoad && ( } source={{uri: this.props.sourceURL}} diff --git a/src/components/Picker/BasePicker.js b/src/components/Picker/BasePicker.js index 550b8a386aa1..697dfc509d22 100644 --- a/src/components/Picker/BasePicker.js +++ b/src/components/Picker/BasePicker.js @@ -258,6 +258,7 @@ function BasePicker(props) { }} pickerProps={{ ref: picker, + tabIndex: -1, onFocus: enableHighlight, onBlur: () => { disableHighlight(); diff --git a/src/components/PlaidLink/index.native.js b/src/components/PlaidLink/index.native.js index cd17453820cf..48cd41e283c3 100644 --- a/src/components/PlaidLink/index.native.js +++ b/src/components/PlaidLink/index.native.js @@ -1,16 +1,13 @@ import {useEffect} from 'react'; import {openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; import Log from '../../libs/Log'; -import CONST from '../../CONST'; import {plaidLinkPropTypes, plaidLinkDefaultProps} from './plaidLinkPropTypes'; function PlaidLink(props) { useDeepLinkRedirector(); usePlaidEmitter((event) => { Log.info('[PlaidLink] Handled Plaid Event: ', false, event); - if (event.eventName === CONST.PLAID.EVENT.ERROR) { - props.onError(event.metadata); - } + props.onEvent(event.eventName, event.metadata); }); useEffect(() => { openLink({ @@ -20,9 +17,6 @@ function PlaidLink(props) { onSuccess: ({publicToken, metadata}) => { props.onSuccess({publicToken, metadata}); }, - onEvent: (event, metadata) => { - props.onEvent(event, metadata); - }, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); props.onExit(); diff --git a/src/components/Reactions/ReportActionItemEmojiReactions.js b/src/components/Reactions/ReportActionItemEmojiReactions.js index ec2755f1a5dd..c1e1764ed9f1 100644 --- a/src/components/Reactions/ReportActionItemEmojiReactions.js +++ b/src/components/Reactions/ReportActionItemEmojiReactions.js @@ -42,7 +42,7 @@ const defaultProps = { function ReportActionItemEmojiReactions(props) { const {reactionListRef} = useContext(ReportScreenContext); - const popoverReactionListAnchor = useRef(null); + const popoverReactionListAnchors = useRef({}); let totalReactionCount = 0; // Each emoji is sorted by the oldest timestamp of user reactions so that they will always appear in the same order for everyone @@ -95,7 +95,7 @@ function ReportActionItemEmojiReactions(props) { }; const onReactionListOpen = (event) => { - reactionListRef.current.showReactionList(event, popoverReactionListAnchor.current, reactionEmojiName, props.reportActionID); + reactionListRef.current.showReactionList(event, popoverReactionListAnchors.current[reactionEmojiName], reactionEmojiName, props.reportActionID); }; return { @@ -112,10 +112,7 @@ function ReportActionItemEmojiReactions(props) { return ( totalReactionCount > 0 && ( - + {_.map(formattedReactions, (reaction) => { if (reaction === null) { return; @@ -135,7 +132,7 @@ function ReportActionItemEmojiReactions(props) { > (popoverReactionListAnchors.current[reaction.reactionEmojiName] = ref)} count={reaction.reactionCount} emojiCodes={reaction.emojiCodes} onPress={reaction.onPress} diff --git a/src/components/ReportActionItem/MoneyReportView.js b/src/components/ReportActionItem/MoneyReportView.js index f863c8994c6f..5b4eaaa37884 100644 --- a/src/components/ReportActionItem/MoneyReportView.js +++ b/src/components/ReportActionItem/MoneyReportView.js @@ -50,7 +50,7 @@ function MoneyReportView(props) { {isSettled && ( - + diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index f760e5d5aeb4..f0f8b8a4b09b 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -3,6 +3,7 @@ import React from 'react'; import _ from 'underscore'; import lodashGet from 'lodash/get'; import {PickerAvoidingView} from 'react-native-picker-select'; +import FocusTrapView from '../FocusTrapView'; import KeyboardAvoidingView from '../KeyboardAvoidingView'; import CONST from '../../CONST'; import styles from '../../styles/styles'; @@ -124,20 +125,26 @@ class ScreenWrapper extends React.Component { style={styles.flex1} enabled={this.props.shouldEnablePickerAvoiding} > - - {this.props.environment === CONST.ENVIRONMENT.DEV && } - {this.props.environment === CONST.ENVIRONMENT.DEV && } - { - // If props.children is a function, call it to provide the insets to the children. - _.isFunction(this.props.children) - ? this.props.children({ - insets, - safeAreaPaddingBottomStyle, - didScreenTransitionEnd: this.state.didScreenTransitionEnd, - }) - : this.props.children - } - {this.props.isSmallScreenWidth && this.props.shouldShowOfflineIndicator && } + + + {this.props.environment === CONST.ENVIRONMENT.DEV && } + {this.props.environment === CONST.ENVIRONMENT.DEV && } + { + // If props.children is a function, call it to provide the insets to the children. + _.isFunction(this.props.children) + ? this.props.children({ + insets, + safeAreaPaddingBottomStyle, + didScreenTransitionEnd: this.state.didScreenTransitionEnd, + }) + : this.props.children + } + {this.props.isSmallScreenWidth && this.props.shouldShowOfflineIndicator && } + diff --git a/src/components/ScreenWrapper/propTypes.js b/src/components/ScreenWrapper/propTypes.js index 83033d9e97b7..c3538b3c026d 100644 --- a/src/components/ScreenWrapper/propTypes.js +++ b/src/components/ScreenWrapper/propTypes.js @@ -48,6 +48,12 @@ const propTypes = { /** Styles for the offline indicator */ offlineIndicatorStyle: stylePropTypes, + + /** Whether to disable the focus trap */ + shouldDisableFocusTrap: PropTypes.bool, + + /** Whether to disable auto focus of the focus trap */ + shouldEnableAutoFocus: PropTypes.bool, }; const defaultProps = { @@ -63,6 +69,8 @@ const defaultProps = { shouldShowOfflineIndicator: true, offlineIndicatorStyle: [], headerGapStyles: [], + shouldDisableFocusTrap: false, + shouldEnableAutoFocus: false, }; export {propTypes, defaultProps}; diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 046b64e9e5c0..e54d64fe56e8 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -1,7 +1,8 @@ -import React, {useEffect, useMemo, useRef, useState} from 'react'; +import React, {useCallback, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import lodashGet from 'lodash/get'; +import {useFocusEffect} from '@react-navigation/native'; import SectionList from '../SectionList'; import Text from '../Text'; import styles from '../../styles/styles'; @@ -11,7 +12,7 @@ import CONST from '../../CONST'; import variables from '../../styles/variables'; import {propTypes as selectionListPropTypes} from './selectionListPropTypes'; import RadioListItem from './RadioListItem'; -import CheckboxListItem from './CheckboxListItem'; +import UserListItem from './UserListItem'; import useKeyboardShortcut from '../../hooks/useKeyboardShortcut'; import SafeAreaConsumer from '../SafeAreaConsumer'; import withKeyboardState, {keyboardStatePropTypes} from '../withKeyboardState'; @@ -42,7 +43,6 @@ function BaseSelectionList({ keyboardType = CONST.KEYBOARD_TYPE.DEFAULT, onChangeText, initiallyFocusedOptionKey = '', - shouldDelayFocus = false, onScroll, onScrollBeginDrag, headerMessage = '', @@ -242,16 +242,20 @@ function BaseSelectionList({ }; const renderItem = ({item, index, section}) => { + const normalizedIndex = index + lodashGet(section, 'indexOffset', 0); const isDisabled = section.isDisabled; - const isFocused = !isDisabled && focusedIndex === index + lodashGet(section, 'indexOffset', 0); + const isFocused = !isDisabled && focusedIndex === normalizedIndex; + // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade. + const showTooltip = normalizedIndex < 10; if (canSelectMultiple) { return ( - selectRow(item, index)} onDismissError={onDismissError} + showTooltip={showTooltip} /> ); } @@ -266,23 +270,20 @@ function BaseSelectionList({ ); }; - /** Focuses the text input when the component mounts. If `props.shouldDelayFocus` is true, we wait for the animation to finish */ - useEffect(() => { - if (shouldShowTextInput) { - if (shouldDelayFocus) { + /** Focuses the text input when the component comes into focus and after any navigation animations finish. */ + useFocusEffect( + useCallback(() => { + if (shouldShowTextInput) { focusTimeoutRef.current = setTimeout(() => textInputRef.current.focus(), CONST.ANIMATED_TRANSITION); - } else { - textInputRef.current.focus(); - } - } - - return () => { - if (!focusTimeoutRef.current) { - return; } - clearTimeout(focusTimeoutRef.current); - }; - }, [shouldDelayFocus, shouldShowTextInput]); + return () => { + if (!focusTimeoutRef.current) { + return; + } + clearTimeout(focusTimeoutRef.current); + }; + }, [shouldShowTextInput]), + ); /** Selects row when pressing Enter */ useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, selectFocusedOption, { @@ -354,7 +355,7 @@ function BaseSelectionList({ disabled={flattenedSections.allOptions.length === flattenedSections.disabledOptionsIndexes.length} /> - {translate('workspace.people.selectAll')} + {translate('workspace.people.selectAll')} )} diff --git a/src/components/SelectionList/CheckboxListItem.js b/src/components/SelectionList/CheckboxListItem.js deleted file mode 100644 index 256182a38e8b..000000000000 --- a/src/components/SelectionList/CheckboxListItem.js +++ /dev/null @@ -1,89 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; -import PressableWithFeedback from '../Pressable/PressableWithFeedback'; -import styles from '../../styles/styles'; -import Text from '../Text'; -import {checkboxListItemPropTypes} from './selectionListPropTypes'; -import Avatar from '../Avatar'; -import OfflineWithFeedback from '../OfflineWithFeedback'; -import CONST from '../../CONST'; -import * as StyleUtils from '../../styles/StyleUtils'; -import Icon from '../Icon'; -import * as Expensicons from '../Icon/Expensicons'; -import themeColors from '../../styles/themes/default'; - -function CheckboxListItem({item, isFocused = false, onSelectRow, onDismissError = () => {}}) { - const hasError = !_.isEmpty(item.errors); - - return ( - onDismissError(item)} - pendingAction={item.pendingAction} - errors={item.errors} - errorRowStyles={styles.ph5} - > - onSelectRow(item)} - disabled={item.isDisabled} - accessibilityLabel={item.text} - accessibilityRole="checkbox" - accessibilityState={{checked: item.isSelected}} - hoverDimmingValue={1} - hoverStyle={styles.hoveredComponentBG} - focusStyle={styles.hoveredComponentBG} - > - - {item.isSelected && ( - - )} - - {Boolean(item.avatar) && ( - - )} - - - {item.text} - - {Boolean(item.alternateText) && ( - - {item.alternateText} - - )} - - {Boolean(item.rightElement) && item.rightElement} - - - ); -} - -CheckboxListItem.displayName = 'CheckboxListItem'; -CheckboxListItem.propTypes = checkboxListItemPropTypes; - -export default CheckboxListItem; diff --git a/src/components/SelectionList/UserListItem.js b/src/components/SelectionList/UserListItem.js new file mode 100644 index 000000000000..a3c25f09af3b --- /dev/null +++ b/src/components/SelectionList/UserListItem.js @@ -0,0 +1,111 @@ +import React from 'react'; +import {View} from 'react-native'; +import _ from 'underscore'; +import lodashGet from 'lodash/get'; +import PressableWithFeedback from '../Pressable/PressableWithFeedback'; +import styles from '../../styles/styles'; +import Text from '../Text'; +import {userListItemPropTypes} from './selectionListPropTypes'; +import Avatar from '../Avatar'; +import OfflineWithFeedback from '../OfflineWithFeedback'; +import CONST from '../../CONST'; +import * as StyleUtils from '../../styles/StyleUtils'; +import Icon from '../Icon'; +import * as Expensicons from '../Icon/Expensicons'; +import themeColors from '../../styles/themes/default'; +import Tooltip from '../Tooltip'; +import UserDetailsTooltip from '../UserDetailsTooltip'; + +function UserListItem({item, isFocused = false, showTooltip, onSelectRow, onDismissError = () => {}}) { + const hasError = !_.isEmpty(item.errors); + + const avatar = ( + + ); + + const text = ( + + {item.text} + + ); + + const alternateText = ( + + {item.alternateText} + + ); + + return ( + onDismissError(item)} + pendingAction={item.pendingAction} + errors={item.errors} + errorRowStyles={styles.ph5} + > + onSelectRow(item)} + disabled={item.isDisabled} + accessibilityLabel={item.text} + accessibilityRole="checkbox" + accessibilityState={{checked: item.isSelected}} + hoverDimmingValue={1} + hoverStyle={styles.hoveredComponentBG} + focusStyle={styles.hoveredComponentBG} + > + + + {item.isSelected && ( + + )} + + + {Boolean(item.avatar) && + (showTooltip ? ( + + {avatar} + + ) : ( + avatar + ))} + + {showTooltip ? {text} : text} + {Boolean(item.alternateText) && (showTooltip ? {alternateText} : alternateText)} + + {Boolean(item.rightElement) && item.rightElement} + + + ); +} + +UserListItem.displayName = 'UserListItem'; +UserListItem.propTypes = userListItemPropTypes; + +export default UserListItem; diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index 9adf42833ebc..0a3c1efdf6a3 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import _ from 'underscore'; import CONST from '../../CONST'; -const checkboxListItemPropTypes = { +const userListItemPropTypes = { /** The section list item */ item: PropTypes.shape({ /** Text to display */ @@ -46,6 +46,9 @@ const checkboxListItemPropTypes = { /** Whether this item is focused (for arrow key controls) */ isFocused: PropTypes.bool, + /** Whether this item should show Tooltip */ + showTooltip: PropTypes.bool.isRequired, + /** Callback to fire when the item is pressed */ onSelectRow: PropTypes.func.isRequired, @@ -90,7 +93,7 @@ const propTypes = { indexOffset: PropTypes.number, /** Array of options */ - data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape(checkboxListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)])), + data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape(userListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)])), /** Whether this section items disabled for selection */ isDisabled: PropTypes.bool, @@ -130,9 +133,6 @@ const propTypes = { /** Item `keyForList` to focus initially */ initiallyFocusedOptionKey: PropTypes.string, - /** Whether to delay focus on the text input when mounting. Used for a smoother animation on Android */ - shouldDelayFocus: PropTypes.bool, - /** Callback to fire when the list is scrolled */ onScroll: PropTypes.func, @@ -158,4 +158,4 @@ const propTypes = { showConfirmButton: PropTypes.bool, }; -export {propTypes, radioListItemPropTypes, checkboxListItemPropTypes}; +export {propTypes, radioListItemPropTypes, userListItemPropTypes}; diff --git a/src/components/SettlementButton.js b/src/components/SettlementButton.js index 21af004a0683..4a6afea9c02c 100644 --- a/src/components/SettlementButton.js +++ b/src/components/SettlementButton.js @@ -1,21 +1,20 @@ +import React, {useEffect, useMemo} from 'react'; import _ from 'underscore'; -import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; -import * as Expensicons from './Icon/Expensicons'; -import Permissions from '../libs/Permissions'; -import ONYXKEYS from '../ONYXKEYS'; import CONST from '../CONST'; +import ONYXKEYS from '../ONYXKEYS'; import compose from '../libs/compose'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import Permissions from '../libs/Permissions'; +import useNetwork from '../hooks/useNetwork'; +import useLocalize from '../hooks/useLocalize'; +import * as ReportUtils from '../libs/ReportUtils'; +import iouReportPropTypes from '../pages/iouReportPropTypes'; import * as PaymentMethods from '../libs/actions/PaymentMethods'; import KYCWall from './KYCWall'; import withNavigation from './withNavigation'; -import {withNetwork} from './OnyxProvider'; -import networkPropTypes from './networkPropTypes'; -import iouReportPropTypes from '../pages/iouReportPropTypes'; -import * as ReportUtils from '../libs/ReportUtils'; +import * as Expensicons from './Icon/Expensicons'; +import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; const propTypes = { /** Callback to execute when this button is pressed. Receives a single payment type argument. */ @@ -27,9 +26,6 @@ const propTypes = { /** Should we show paypal option */ shouldShowPaypal: PropTypes.bool, - /** Information about the network */ - network: networkPropTypes.isRequired, - /** When the button is opened via an IOU, ID for the chatReport that the IOU is linked to */ chatReportID: PropTypes.string, @@ -60,25 +56,41 @@ const propTypes = { /** The size of button size */ buttonSize: PropTypes.oneOf(_.values(CONST.DROPDOWN_BUTTON_SIZE)), - /** The anchor alignment of the popover menu */ + /** Route for the Add Bank Account screen for a given navigation stack */ + addBankAccountRoute: PropTypes.string, + + /** Route for the Add Debit Card screen for a given navigation stack */ + addDebitCardRoute: PropTypes.string, + /** Whether the button should be disabled */ + isDisabled: PropTypes.bool, + + /** Whether we should show a loading state for the main button */ + isLoading: PropTypes.bool, + + /** The anchor alignment of the popover menu */ anchorAlignment: PropTypes.shape({ horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)), vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)), }), - - ...withLocalizePropTypes, }; const defaultProps = { + isLoading: false, + isDisabled: false, + addBankAccountRoute: '', + addDebitCardRoute: '', currency: CONST.CURRENCY.USD, shouldShowPaypal: false, chatReportID: '', - betas: [], + + // The "betas" array, "iouReport" and "nvp_lastPaymentMethod" objects needs to be stable to prevent the "useMemo" + // hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT + betas: CONST.EMPTY_ARRAY, + iouReport: CONST.EMPTY_OBJECT, + nvp_lastPaymentMethod: CONST.EMPTY_OBJECT, shouldShowPaymentOptions: false, - nvp_lastPaymentMethod: {}, style: [], - iouReport: {}, policyID: '', formattedAmount: '', buttonSize: CONST.DROPDOWN_BUTTON_SIZE.MEDIUM, @@ -88,43 +100,64 @@ const defaultProps = { }, }; -class SettlementButton extends React.Component { - componentDidMount() { +function SettlementButton({ + addDebitCardRoute, + addBankAccountRoute, + anchorAlignment, + betas, + buttonSize, + chatReportID, + currency, + enablePaymentsRoute, + iouReport, + isDisabled, + isLoading, + formattedAmount, + nvp_lastPaymentMethod, + onPress, + policyID, + shouldShowPaymentOptions, + shouldShowPaypal, + style, +}) { + const {translate} = useLocalize(); + const {isOffline} = useNetwork(); + + useEffect(() => { PaymentMethods.openWalletPage(); - } + }, []); - getButtonOptionsFromProps() { + const paymentButtonOptions = useMemo(() => { const buttonOptions = []; - const isExpenseReport = ReportUtils.isExpenseReport(this.props.iouReport); + const isExpenseReport = ReportUtils.isExpenseReport(iouReport); const paymentMethods = { [CONST.IOU.PAYMENT_TYPE.EXPENSIFY]: { - text: this.props.translate('iou.settleExpensify', {formattedAmount: this.props.formattedAmount || ''}), + text: translate('iou.settleExpensify', {formattedAmount}), icon: Expensicons.Wallet, value: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, }, [CONST.IOU.PAYMENT_TYPE.VBBA]: { - text: this.props.translate('iou.settleExpensify', {formattedAmount: this.props.formattedAmount || ''}), + text: translate('iou.settleExpensify', {formattedAmount}), icon: Expensicons.Wallet, value: CONST.IOU.PAYMENT_TYPE.VBBA, }, [CONST.IOU.PAYMENT_TYPE.PAYPAL_ME]: { - text: this.props.translate('iou.settlePaypalMe', {formattedAmount: this.props.formattedAmount || ''}), + text: translate('iou.settlePaypalMe', {formattedAmount}), icon: Expensicons.PayPal, value: CONST.IOU.PAYMENT_TYPE.PAYPAL_ME, }, [CONST.IOU.PAYMENT_TYPE.ELSEWHERE]: { - text: this.props.translate('iou.payElsewhere'), + text: translate('iou.payElsewhere'), icon: Expensicons.Cash, value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; - const canUseWallet = - !isExpenseReport && this.props.currency === CONST.CURRENCY.USD && Permissions.canUsePayWithExpensify(this.props.betas) && Permissions.canUseWallet(this.props.betas); + const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD && Permissions.canUsePayWithExpensify(betas) && Permissions.canUseWallet(betas); // To achieve the one tap pay experience we need to choose the correct payment type as default, // if user already paid for some request or expense, let's use the last payment method or use default. - let paymentMethod = this.props.nvp_lastPaymentMethod[this.props.policyID] || ''; - if (!this.props.shouldShowPaymentOptions) { + let paymentMethod = nvp_lastPaymentMethod[policyID] || ''; + if (!shouldShowPaymentOptions) { if (!paymentMethod) { // In case the user hasn't paid a request yet, let's default to VBBA payment type in case of expense reports if (isExpenseReport) { @@ -138,7 +171,7 @@ class SettlementButton extends React.Component { } // In case the last payment method has been PayPal, but this request is made in currency unsupported by Paypal, default to Elsewhere - if (paymentMethod === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME && !_.includes(CONST.PAYPAL_SUPPORTED_CURRENCIES, this.props.currency)) { + if (paymentMethod === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME && !_.includes(CONST.PAYPAL_SUPPORTED_CURRENCIES, currency)) { paymentMethod = CONST.IOU.PAYMENT_TYPE.ELSEWHERE; } @@ -146,7 +179,7 @@ class SettlementButton extends React.Component { return [ { ...paymentMethods[paymentMethod], - text: paymentMethod === CONST.IOU.PAYMENT_TYPE.ELSEWHERE ? this.props.translate('iou.payElsewhere') : this.props.translate('iou.pay'), + text: paymentMethod === CONST.IOU.PAYMENT_TYPE.ELSEWHERE ? translate('iou.payElsewhere') : translate('iou.pay'), }, ]; } @@ -156,7 +189,7 @@ class SettlementButton extends React.Component { if (isExpenseReport) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); } - if (this.props.shouldShowPaypal && _.includes(CONST.PAYPAL_SUPPORTED_CURRENCIES, this.props.currency)) { + if (shouldShowPaypal && _.includes(CONST.PAYPAL_SUPPORTED_CURRENCIES, currency)) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.PAYPAL_ME]); } buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); @@ -166,50 +199,49 @@ class SettlementButton extends React.Component { return _.sortBy(buttonOptions, (method) => (method.value === paymentMethod ? 0 : 1)); } return buttonOptions; - } - - render() { - return ( - this.props.onPress(iouPaymentType)} - enablePaymentsRoute={this.props.enablePaymentsRoute} - addBankAccountRoute={this.props.addBankAccountRoute} - addDebitCardRoute={this.props.addDebitCardRoute} - isDisabled={this.props.network.isOffline} - chatReportID={this.props.chatReportID} - iouReport={this.props.iouReport} - > - {(triggerKYCFlow, buttonRef) => ( - { - if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { - triggerKYCFlow(event, iouPaymentType); - return; - } - - this.props.onPress(iouPaymentType); - }} - options={this.getButtonOptionsFromProps()} - style={this.props.style} - buttonSize={this.props.buttonSize} - anchorAlignment={this.props.anchorAlignment} - /> - )} - - ); - } + }, [betas, currency, formattedAmount, iouReport, nvp_lastPaymentMethod, policyID, shouldShowPaymentOptions, shouldShowPaypal, translate]); + + const selectPaymentType = (event, iouPaymentType, triggerKYCFlow) => { + if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { + triggerKYCFlow(event, iouPaymentType); + return; + } + + onPress(iouPaymentType); + }; + + return ( + + {(triggerKYCFlow, buttonRef) => ( + selectPaymentType(event, iouPaymentType, triggerKYCFlow)} + options={paymentButtonOptions} + style={style} + buttonSize={buttonSize} + anchorAlignment={anchorAlignment} + /> + )} + + ); } SettlementButton.propTypes = propTypes; SettlementButton.defaultProps = defaultProps; +SettlementButton.displayName = 'SettlementButton'; export default compose( withNavigation, - withLocalize, - withNetwork(), withOnyx({ betas: { key: ONYXKEYS.BETAS, diff --git a/src/components/ShowContextMenuContext.js b/src/components/ShowContextMenuContext.js index df522dec8f10..fff233162d74 100644 --- a/src/components/ShowContextMenuContext.js +++ b/src/components/ShowContextMenuContext.js @@ -2,6 +2,7 @@ import React from 'react'; import * as ReportActionContextMenu from '../pages/home/report/ContextMenu/ReportActionContextMenu'; import * as ContextMenuActions from '../pages/home/report/ContextMenu/ContextMenuActions'; import * as DeviceCapabilities from '../libs/DeviceCapabilities'; +import * as ReportUtils from '../libs/ReportUtils'; const ShowContextMenuContext = React.createContext({ anchor: null, @@ -32,7 +33,8 @@ function showContextMenuForReport(event, anchor, reportID, action, checkIfContex '', anchor, reportID, - action, + action.reportActionID, + ReportUtils.getOriginalReportID(reportID, action), '', checkIfContextMenuActive, checkIfContextMenuActive, diff --git a/src/components/SignInButtons/GoogleSignIn/index.website.js b/src/components/SignInButtons/GoogleSignIn/index.website.js index 33d6a2e382c9..5362433142af 100644 --- a/src/components/SignInButtons/GoogleSignIn/index.website.js +++ b/src/components/SignInButtons/GoogleSignIn/index.website.js @@ -68,6 +68,8 @@ function GoogleSignIn({translate, isDesktopFlow}) { }; }, [loadScript]); + // willChangeTransform is used to prevent the icon cut in safari when the overflow hidden and width given to the parent + // ref: https://stackoverflow.com/questions/75306089/safari-when-using-border-radius-and-overflow-hidden-to-parent-and-the-child-th return isDesktopFlow ? (
) : ( - +
- _.map(translate('allStates'), (state) => ({ - value: state.stateISO, - keyForList: state.stateISO, - text: state.stateName, - isSelected: currentState === state.stateISO, - searchValue: StringUtils.sanitizeString(`${state.stateISO}${state.stateName}`), - })), + _.map(_.keys(COMMON_CONST.STATES), (state) => { + const stateName = translate(`allStates.${state}.stateName`); + const stateISO = translate(`allStates.${state}.stateISO`); + return { + value: stateISO, + keyForList: stateISO, + text: stateName, + isSelected: currentState === stateISO, + searchValue: StringUtils.sanitizeString(`${stateISO}${stateName}`), + }; + }), [translate, currentState], ); @@ -92,7 +97,6 @@ function StateSelectorModal({currentState, isVisible, onClose, onStateSelected, sections={[{data: searchResults, indexOffset: 0}]} onSelectRow={onStateSelected} onChangeText={setSearchValue} - shouldDelayFocus initiallyFocusedOptionKey={currentState} /> diff --git a/src/components/StatePicker/index.js b/src/components/StatePicker/index.js index a4d3ea5e8133..142654b82cd1 100644 --- a/src/components/StatePicker/index.js +++ b/src/components/StatePicker/index.js @@ -1,6 +1,8 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import styles from '../../styles/styles'; import MenuItemWithTopDescription from '../MenuItemWithTopDescription'; import useLocalize from '../../hooks/useLocalize'; @@ -35,7 +37,6 @@ const defaultProps = { function StatePicker({value, errorText, onInputChange, forwardedRef, label}) { const {translate} = useLocalize(); - const allStates = translate('allStates'); const [isPickerVisible, setIsPickerVisible] = useState(false); const [searchValue, setSearchValue] = useState(''); @@ -52,7 +53,7 @@ function StatePicker({value, errorText, onInputChange, forwardedRef, label}) { hidePickerModal(); }; - const title = allStates[value] ? allStates[value].stateName : ''; + const title = value && _.keys(COMMON_CONST.STATES).includes(value) ? translate(`allStates.${value}.stateName`) : ''; const descStyle = title.length === 0 ? styles.textNormal : null; return ( diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js new file mode 100644 index 000000000000..25021bd817d7 --- /dev/null +++ b/src/components/TagPicker/index.js @@ -0,0 +1,90 @@ +import React, {useMemo} from 'react'; +import _ from 'underscore'; +import lodashGet from 'lodash/get'; +import {withOnyx} from 'react-native-onyx'; +import ONYXKEYS from '../../ONYXKEYS'; +import styles from '../../styles/styles'; +import Navigation from '../../libs/Navigation/Navigation'; +import ROUTES from '../../ROUTES'; +import useLocalize from '../../hooks/useLocalize'; +import * as OptionsListUtils from '../../libs/OptionsListUtils'; +import OptionsSelector from '../OptionsSelector'; +import {propTypes, defaultProps} from './tagPickerPropTypes'; + +function TagPicker({policyTags, reportID, tag, iouType, iou}) { + const {translate} = useLocalize(); + + const selectedOptions = useMemo(() => { + if (!iou.tag) { + return []; + } + + return [ + { + name: iou.tag, + enabled: true, + }, + ]; + }, [iou.tag]); + + // Only shows one section, which will be the default behavior if there are + // less than 8 policy tags + // TODO: support sections with search + const sections = useMemo(() => { + const tagList = _.chain(lodashGet(policyTags, [tag, 'tags'], {})) + .values() + .map((t) => ({ + text: t.name, + keyForList: t.name, + tooltipText: t.name, + })) + .value(); + + return [ + { + data: tagList, + }, + ]; + }, [policyTags, tag]); + + const headerMessage = OptionsListUtils.getHeaderMessage(lodashGet(sections, '[0].data.length', 0) > 0, false, ''); + + const navigateBack = () => { + Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID)); + }; + + const updateTag = () => { + // TODO: add logic to save the selected tag + navigateBack(); + }; + + return ( + + ); +} + +TagPicker.displayName = 'TagPicker'; +TagPicker.propTypes = propTypes; +TagPicker.defaultProps = defaultProps; + +export default withOnyx({ + policyTags: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + }, + policyRecentlyUsedTags: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + }, + iou: { + key: ONYXKEYS.IOU, + }, +})(TagPicker); diff --git a/src/components/TagPicker/tagPickerPropTypes.js b/src/components/TagPicker/tagPickerPropTypes.js new file mode 100644 index 000000000000..ad57a0409f15 --- /dev/null +++ b/src/components/TagPicker/tagPickerPropTypes.js @@ -0,0 +1,43 @@ +import PropTypes from 'prop-types'; +import tagPropTypes from '../tagPropTypes'; +import {iouPropTypes, iouDefaultProps} from '../../pages/iou/propTypes'; + +const propTypes = { + /** The report ID of the IOU */ + reportID: PropTypes.string.isRequired, + + /** The policyID we are getting tags for */ + policyID: PropTypes.string.isRequired, + + /** The name of tag list we are getting tags for */ + tag: PropTypes.string.isRequired, + + /** The type of IOU report, i.e. bill, request, send */ + iouType: PropTypes.string.isRequired, + + /** Callback to submit the selected tag */ + onSubmit: PropTypes.func, + + /* Onyx Props */ + /** Collection of tags attached to a policy */ + policyTags: PropTypes.objectOf( + PropTypes.shape({ + name: PropTypes.string, + tags: PropTypes.objectOf(tagPropTypes), + }), + ), + + /** List of recently used tags */ + policyRecentlyUsedTags: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)), + + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + iou: iouPropTypes, +}; + +const defaultProps = { + policyTags: {}, + policyRecentlyUsedTags: {}, + iou: iouDefaultProps, +}; + +export {propTypes, defaultProps}; diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index 297d7de028fb..19453be054d4 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -331,6 +331,8 @@ function BaseTextInput(props) { // Stop scrollbar flashing when breaking lines with autoGrowHeight enabled. props.autoGrowHeight && StyleUtils.getAutoGrowHeightInputStyle(textInputHeight, maxHeight), + // Add disabled color theme when field is not editable. + props.disabled && styles.textInputDisabled, ]} multiline={isMultiline} maxLength={props.maxLength} diff --git a/src/components/Tooltip/TooltipRenderedOnPageBody.js b/src/components/Tooltip/TooltipRenderedOnPageBody.js index c8624421f871..f61ecaee1059 100644 --- a/src/components/Tooltip/TooltipRenderedOnPageBody.js +++ b/src/components/Tooltip/TooltipRenderedOnPageBody.js @@ -86,6 +86,7 @@ function TooltipRenderedOnPageBody(props) { const {animationStyle, rootWrapperStyle, textStyle, pointerWrapperStyle, pointerStyle} = useMemo( () => getTooltipStyles( + rootWrapper.current, props.animation, props.windowWidth, props.xOffset, @@ -97,7 +98,6 @@ function TooltipRenderedOnPageBody(props) { wrapperMeasuredHeight, props.shiftHorizontal, props.shiftVertical, - rootWrapper.current, ), [ props.animation, diff --git a/src/components/UnreadActionIndicator.js b/src/components/UnreadActionIndicator.js index 5273ab52ec28..ff1090640570 100755 --- a/src/components/UnreadActionIndicator.js +++ b/src/components/UnreadActionIndicator.js @@ -10,6 +10,7 @@ function UnreadActionIndicator(props) { diff --git a/src/components/tagPropTypes.js b/src/components/tagPropTypes.js new file mode 100644 index 000000000000..29d913dcd035 --- /dev/null +++ b/src/components/tagPropTypes.js @@ -0,0 +1,12 @@ +import PropTypes from 'prop-types'; + +export default PropTypes.shape({ + /** Name of a tag */ + name: PropTypes.string.isRequired, + + /** Flag that determines if a tag is active and able to be selected */ + enabled: PropTypes.bool.isRequired, + + /** "General Ledger code" that corresponds to this tag in an accounting system. Similar to an ID. */ + 'GL Code': PropTypes.string, +}); diff --git a/src/components/withTheme.js b/src/components/withTheme.js new file mode 100644 index 000000000000..99de2a2c7fc7 --- /dev/null +++ b/src/components/withTheme.js @@ -0,0 +1,40 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import useTheme from '../styles/themes/useTheme'; +import getComponentDisplayName from '../libs/getComponentDisplayName'; +import refPropTypes from './refPropTypes'; + +const withThemePropTypes = { + theme: PropTypes.object.isRequired, +}; + +export default function withTheme(WrappedComponent) { + function WithTheme(props) { + const theme = useTheme(); + return ( + + ); + } + + WithTheme.displayName = `withTheme(${getComponentDisplayName(WrappedComponent)})`; + WithTheme.propTypes = { + forwardedRef: refPropTypes, + }; + WithTheme.defaultProps = { + forwardedRef: () => {}, + }; + return React.forwardRef((props, ref) => ( + + )); +} + +export {withThemePropTypes}; diff --git a/src/components/withThemeStyles.js b/src/components/withThemeStyles.js new file mode 100644 index 000000000000..0320fcb71808 --- /dev/null +++ b/src/components/withThemeStyles.js @@ -0,0 +1,40 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import useThemeStyles from '../styles/useThemeStyles'; +import getComponentDisplayName from '../libs/getComponentDisplayName'; +import refPropTypes from './refPropTypes'; + +const withThemeStylesPropTypes = { + themeStyles: PropTypes.object.isRequired, +}; + +export default function withThemeStyles(WrappedComponent) { + function WithThemeStyles(props) { + const themeStyles = useThemeStyles(); + return ( + + ); + } + + WithThemeStyles.displayName = `withThemeStyles(${getComponentDisplayName(WrappedComponent)})`; + WithThemeStyles.propTypes = { + forwardedRef: refPropTypes, + }; + WithThemeStyles.defaultProps = { + forwardedRef: () => {}, + }; + return React.forwardRef((props, ref) => ( + + )); +} + +export {withThemeStylesPropTypes}; diff --git a/src/hooks/useArrowKeyFocusManager.js b/src/hooks/useArrowKeyFocusManager.js index fdfdf07c99a7..58cecb169249 100644 --- a/src/hooks/useArrowKeyFocusManager.js +++ b/src/hooks/useArrowKeyFocusManager.js @@ -2,10 +2,6 @@ import {useState, useEffect, useCallback, useMemo} from 'react'; import useKeyboardShortcut from './useKeyboardShortcut'; import CONST from '../CONST'; -// Creating a default array this way because objects ({}) and arrays ([]) are not stable types. -// The "disabledIndexes" array needs to be stable to prevent the "useCallback" hook from being recreated unnecessarily. -// Freezing the array ensures that it cannot be unintentionally modified. -const EMPTY_ARRAY = Object.freeze([]); /** * A hook that makes it easy to use the arrow keys to manage focus of items in a list * @@ -24,7 +20,10 @@ export default function useArrowKeyFocusManager({ maxIndex, onFocusedIndexChange = () => {}, initialFocusedIndex = 0, - disabledIndexes = EMPTY_ARRAY, + + // The "disabledIndexes" array needs to be stable to prevent the "useCallback" hook from being recreated unnecessarily. + // Hence the use of CONST.EMPTY_ARRAY. + disabledIndexes = CONST.EMPTY_ARRAY, shouldExcludeTextAreaNodes = true, isActive, }) { diff --git a/src/hooks/useKeyboardShortcut.js b/src/hooks/useKeyboardShortcut.js index 9b7244176864..b8e297c966ed 100644 --- a/src/hooks/useKeyboardShortcut.js +++ b/src/hooks/useKeyboardShortcut.js @@ -1,10 +1,6 @@ import {useEffect} from 'react'; import KeyboardShortcut from '../libs/KeyboardShortcut'; - -// Creating a default array this way because objects ({}) and arrays ([]) are not stable types. -// The "excludedNodes" array needs to be stable to prevent the "useEffect" hook from being recreated unnecessarily. -// Freezing the array ensures that it cannot be unintentionally modified. -const EMPTY_ARRAY = Object.freeze([]); +import CONST from '../CONST'; /** * Register a keyboard shortcut handler. @@ -15,7 +11,17 @@ const EMPTY_ARRAY = Object.freeze([]); * @param {Object} [config] */ export default function useKeyboardShortcut(shortcut, callback, config = {}) { - const {captureOnInputs = true, shouldBubble = false, priority = 0, shouldPreventDefault = true, excludedNodes = EMPTY_ARRAY, isActive = true} = config; + const { + captureOnInputs = true, + shouldBubble = false, + priority = 0, + shouldPreventDefault = true, + + // The "excludedNodes" array needs to be stable to prevent the "useEffect" hook from being recreated unnecessarily. + // Hence the use of CONST.EMPTY_ARRAY. + excludedNodes = CONST.EMPTY_ARRAY, + isActive = true, + } = config; useEffect(() => { if (isActive) { diff --git a/src/languages/en.ts b/src/languages/en.ts index c863caae67ff..03adaa1e66b1 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -38,7 +38,7 @@ import type { SettledAfterAddedBankAccountParams, PaidElsewhereWithAmountParams, PaidUsingPaypalWithAmountParams, - PaidUsingExpensifyWithAmountParams, + PaidWithExpensifyWithAmountParams, ThreadRequestReportNameParams, ThreadSentMoneyReportNameParams, SizeExceededParams, @@ -68,9 +68,23 @@ import type { OOOEventSummaryPartialDayParams, ParentNavigationSummaryParams, ManagerApprovedParams, + SetTheRequestParams, + UpdatedTheRequestParams, + RemovedTheRequestParams, + TagSelectionParams, + TranslationBase, } from './types'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; +type StateValue = { + stateISO: string; + stateName: string; +}; + +type States = Record; + +type AllCountries = Record; + /* eslint-disable max-len */ export default { common: { @@ -230,6 +244,7 @@ export default { showMore: 'Show more', merchant: 'Merchant', category: 'Category', + tag: 'Tag', receipt: 'Receipt', replace: 'Replace', distance: 'Distance', @@ -495,6 +510,7 @@ export default { pending: 'Pending', deleteReceipt: 'Delete receipt', receiptScanning: 'Receipt scan in progress…', + receiptMissingDetails: 'Receipt missing details', receiptStatusTitle: 'Scanning…', receiptStatusText: "Only you can see this receipt when it's scanning. Check back later or enter the details now.", requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} requests${scanningReceipts > 0 ? `, ${scanningReceipts} scanning` : ''}`, @@ -520,11 +536,17 @@ export default { `${submitterDisplayName} added a bank account. The ${amount} payment has been made.`, paidElsewhereWithAmount: ({amount}: PaidElsewhereWithAmountParams) => `paid ${amount} elsewhere`, paidUsingPaypalWithAmount: ({amount}: PaidUsingPaypalWithAmountParams) => `paid ${amount} using Paypal.me`, - paidUsingExpensifyWithAmount: ({amount}: PaidUsingExpensifyWithAmountParams) => `paid ${amount} using Expensify`, + paidWithExpensifyWithAmount: ({amount}: PaidWithExpensifyWithAmountParams) => `paid ${amount} with Expensify`, noReimbursableExpenses: 'This report has an invalid amount', pendingConversionMessage: "Total will update when you're back online", + changedTheRequest: 'changed the request', + setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `set the ${valueName} to ${newValueToDisplay}`, + removedTheRequest: ({valueName, oldValueToDisplay}: RemovedTheRequestParams) => `removed the ${valueName} (previously ${oldValueToDisplay})`, + updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => + `changed the ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`, threadRequestReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} request${comment ? ` for ${comment}` : ''}`, threadSentMoneyReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} sent${comment ? ` for ${comment}` : ''}`, + tagSelection: ({tagName}: TagSelectionParams) => `Select a ${tagName} to add additional organization to your money`, error: { invalidSplit: 'Split amounts do not equal total amount', other: 'Unexpected error, please try again later', @@ -979,7 +1001,7 @@ export default { notHere: "Hmm... it's not here", pageNotFound: 'Oops, this page cannot be found', noAccess: "You don't have access to this chat", - goBackHome: 'Go back to Home page', + goBackHome: 'Go back to home page', }, setPasswordPage: { enterPassword: 'Enter a password', @@ -1652,8 +1674,8 @@ export default { createAccount: 'Create A New Account', logIn: 'Log In', }, - allStates: COMMON_CONST.STATES, - allCountries: CONST.ALL_COUNTRIES, + allStates: COMMON_CONST.STATES as States, + allCountries: CONST.ALL_COUNTRIES as AllCountries, accessibilityHints: { navigateToChatsList: 'Navigate back to chats list', chatWelcomeMessage: 'Chat welcome message', @@ -1747,14 +1769,4 @@ export default { selectSuggestedAddress: 'Please select a suggested address', }, }, - demos: { - saastr: { - signInWelcome: 'Welcome to SaaStr! Hop in to start networking now.', - heroBody: 'Use New Expensify for event updates, networking, social chatter, and to get paid back for lunch!', - }, - sbe: { - signInWelcome: 'Welcome to Small Business Expo! Get paid back for your ride.', - heroBody: 'Use New Expensify for event updates, networking, social chatter, and to get paid back for your ride to or from the show!', - }, - }, -} as const; +} satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index fd98e3ef51fa..7315c42cebab 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -38,7 +38,7 @@ import type { SettledAfterAddedBankAccountParams, PaidElsewhereWithAmountParams, PaidUsingPaypalWithAmountParams, - PaidUsingExpensifyWithAmountParams, + PaidWithExpensifyWithAmountParams, ThreadRequestReportNameParams, ThreadSentMoneyReportNameParams, SizeExceededParams, @@ -68,6 +68,11 @@ import type { OOOEventSummaryPartialDayParams, ParentNavigationSummaryParams, ManagerApprovedParams, + SetTheRequestParams, + UpdatedTheRequestParams, + RemovedTheRequestParams, + TagSelectionParams, + EnglishTranslation, } from './types'; /* eslint-disable max-len */ @@ -229,6 +234,7 @@ export default { showMore: 'Mostrar más', merchant: 'Comerciante', category: 'Categoría', + tag: 'Etiqueta', receipt: 'Recibo', replace: 'Sustituir', distance: 'Distancia', @@ -496,6 +502,7 @@ export default { pending: 'Pendiente', deleteReceipt: 'Eliminar recibo', receiptScanning: 'Escaneo de recibo en curso…', + receiptMissingDetails: 'Recibo con campos vacíos', receiptStatusTitle: 'Escaneando…', receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.', requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} solicitudes${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}`, @@ -521,11 +528,18 @@ export default { `${submitterDisplayName} añadió una cuenta bancaria. El pago de ${amount} se ha realizado.`, paidElsewhereWithAmount: ({amount}: PaidElsewhereWithAmountParams) => `pagó ${amount} de otra forma`, paidUsingPaypalWithAmount: ({amount}: PaidUsingPaypalWithAmountParams) => `pagó ${amount} con PayPal.me`, - paidUsingExpensifyWithAmount: ({amount}: PaidUsingExpensifyWithAmountParams) => `pagó ${amount} con Expensify`, + paidWithExpensifyWithAmount: ({amount}: PaidWithExpensifyWithAmountParams) => `pagó ${amount} con Expensify`, noReimbursableExpenses: 'El importe de este informe no es válido', pendingConversionMessage: 'El total se actualizará cuando estés online', + changedTheRequest: 'cambió la solicitud', + setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `estableció ${valueName === 'comerciante' ? 'el' : 'la'} ${valueName} a ${newValueToDisplay}`, + removedTheRequest: ({valueName, oldValueToDisplay}: RemovedTheRequestParams) => + `eliminó ${valueName === 'comerciante' ? 'el' : 'la'} ${valueName} (previamente ${oldValueToDisplay})`, + updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => + `cambío ${valueName === 'comerciante' ? 'el' : 'la'} ${valueName} a ${newValueToDisplay} (previamente ${oldValueToDisplay})`, threadRequestReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `Solicitud de ${formattedAmount}${comment ? ` para ${comment}` : ''}`, threadSentMoneyReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} enviado${comment ? ` para ${comment}` : ''}`, + tagSelection: ({tagName}: TagSelectionParams) => `Seleccione una ${tagName} para organizar mejor tu dinero`, error: { invalidSplit: 'La suma de las partes no equivale al monto total', other: 'Error inesperado, por favor inténtalo más tarde', @@ -2238,15 +2252,4 @@ export default { selectSuggestedAddress: 'Por favor, selecciona una dirección sugerida', }, }, - demos: { - saastr: { - signInWelcome: '¡Bienvenido a SaaStr! Entra y empieza a establecer contactos.', - heroBody: 'Utiliza New Expensify para estar al día de los eventos, establecer contactos, charlar en las redes sociales, ¡y para que te devuelvan el dinero de la comida!', - }, - sbe: { - signInWelcome: '¡Bienvenido a Small Business Expo! Recupera el dinero de tu viaje.', - heroBody: - 'Utiliza New Expensify para estar al día de los eventos, establecer contactos, charlar en las redes sociales y para que te paguen el viaje de ida y vuelta a la conferencia.', - }, - }, -}; +} satisfies EnglishTranslation; diff --git a/src/languages/translations.ts b/src/languages/translations.ts index a2d27baa26c9..d228394589b2 100644 --- a/src/languages/translations.ts +++ b/src/languages/translations.ts @@ -1,10 +1,50 @@ import en from './en'; import es from './es'; import esES from './es-ES'; +import type {TranslationBase, TranslationFlatObject} from './types'; + +/** + * Converts an object to it's flattened version. + * + * Ex: + * Input: { common: { yes: "Yes", no: "No" }} + * Output: { "common.yes": "Yes", "common.no": "No" } + */ +// Necessary to export so that it is accessible to the unit tests +// eslint-disable-next-line rulesdir/no-inline-named-export +export function flattenObject(obj: TranslationBase): TranslationFlatObject { + const result: Record = {}; + + const recursive = (data: TranslationBase, key: string): void => { + // If the data is a function or not a object (eg. a string or array), + // it's the final value for the key being built and there is no need + // for more recursion + if (typeof data === 'function' || Array.isArray(data) || !(typeof data === 'object' && !!data)) { + result[key] = data; + } else { + let isEmpty = true; + + // Recursive call to the keys and connect to the respective data + Object.keys(data).forEach((k) => { + isEmpty = false; + recursive(data[k] as TranslationBase, key ? `${key}.${k}` : k); + }); + + // Check for when the object is empty but a key exists, so that + // it defaults to an empty object + if (isEmpty && key) { + result[key] = ''; + } + } + }; + + recursive(obj, ''); + return result as TranslationFlatObject; +} export default { - en, - es, + en: flattenObject(en), + es: flattenObject(es), // eslint-disable-next-line @typescript-eslint/naming-convention 'es-ES': esES, }; diff --git a/src/languages/types.ts b/src/languages/types.ts index 50290fb5776c..565b5933b989 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -1,3 +1,5 @@ +import en from './en'; + type AddressLineParams = { lineNumber: number; }; @@ -126,7 +128,7 @@ type PaidElsewhereWithAmountParams = {amount: string}; type PaidUsingPaypalWithAmountParams = {amount: string}; -type PaidUsingExpensifyWithAmountParams = {amount: string}; +type PaidWithExpensifyWithAmountParams = {amount: string}; type ThreadRequestReportNameParams = {formattedAmount: string; comment: string}; @@ -184,7 +186,56 @@ type OOOEventSummaryPartialDayParams = {summary: string; timePeriod: string; dat type ParentNavigationSummaryParams = {rootReportName: string; workspaceName: string}; +type SetTheRequestParams = {valueName: string; newValueToDisplay: string}; + +type RemovedTheRequestParams = {valueName: string; oldValueToDisplay: string}; + +type UpdatedTheRequestParams = {valueName: string; newValueToDisplay: string; oldValueToDisplay: string}; + +type TagSelectionParams = {tagName: string}; + +/* Translation Object types */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type TranslationBaseValue = string | string[] | ((...args: any[]) => string); + +type TranslationBase = {[key: string]: TranslationBaseValue | TranslationBase}; + +/* Flat Translation Object types */ +// Flattens an object and returns concatenations of all the keys of nested objects +type FlattenObject = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [TKey in keyof TObject]: TObject[TKey] extends (...args: any[]) => any + ? `${TPrefix}${TKey & string}` + : // eslint-disable-next-line @typescript-eslint/no-explicit-any + TObject[TKey] extends any[] + ? `${TPrefix}${TKey & string}` + : // eslint-disable-next-line @typescript-eslint/ban-types + TObject[TKey] extends object + ? FlattenObject + : `${TPrefix}${TKey & string}`; +}[keyof TObject]; + +// Retrieves a type for a given key path (calculated from the type above) +type TranslateType = TPath extends keyof TObject + ? TObject[TPath] + : TPath extends `${infer TKey}.${infer TRest}` + ? TKey extends keyof TObject + ? TranslateType + : never + : never; + +type EnglishTranslation = typeof en; + +type TranslationPaths = FlattenObject; + +type TranslationFlatObject = { + [TKey in TranslationPaths]: TranslateType; +}; + export type { + TranslationBase, + EnglishTranslation, + TranslationFlatObject, AddressLineParams, CharacterLimitParams, MaxParticipantsReachedParams, @@ -223,7 +274,7 @@ export type { SettledAfterAddedBankAccountParams, PaidElsewhereWithAmountParams, PaidUsingPaypalWithAmountParams, - PaidUsingExpensifyWithAmountParams, + PaidWithExpensifyWithAmountParams, ThreadRequestReportNameParams, ThreadSentMoneyReportNameParams, SizeExceededParams, @@ -252,4 +303,8 @@ export type { OOOEventSummaryFullDayParams, OOOEventSummaryPartialDayParams, ParentNavigationSummaryParams, + SetTheRequestParams, + UpdatedTheRequestParams, + RemovedTheRequestParams, + TagSelectionParams, }; diff --git a/src/libs/Browser/index.js b/src/libs/Browser/index.ts similarity index 100% rename from src/libs/Browser/index.js rename to src/libs/Browser/index.ts diff --git a/src/libs/Browser/index.web.js b/src/libs/Browser/index.web.ts similarity index 88% rename from src/libs/Browser/index.web.js rename to src/libs/Browser/index.web.ts index 32f6392aef76..064358c6bed5 100644 --- a/src/libs/Browser/index.web.js +++ b/src/libs/Browser/index.web.ts @@ -5,12 +5,12 @@ import ROUTES from '../../ROUTES'; /** * Fetch browser name from UA string * - * @return {String} e.g. Chrome */ -function getBrowser() { +function getBrowser(): string { const {userAgent} = window.navigator; - let match = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))/i) || []; - let temp; + const match = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))/i) ?? []; + let temp: RegExpMatchArray | null; + let browserName = ''; if (/trident/i.test(match[1])) { return 'IE'; @@ -28,15 +28,14 @@ function getBrowser() { } } - match = match[1] ? match[1] : navigator.appName; - return match ? match.toLowerCase() : CONST.BROWSER.OTHER; + browserName = match[1] ?? navigator.appName; + return browserName ? browserName.toLowerCase() : CONST.BROWSER.OTHER; } /** * Whether the platform is a mobile browser. * https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent * - * @returns {Boolean} */ function isMobile() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Silk|Opera Mini/i.test(navigator.userAgent); @@ -45,7 +44,6 @@ function isMobile() { /** * Checks if requesting user agent is Safari browser on a mobile device * - * @returns {Boolean} */ function isMobileSafari() { const userAgent = navigator.userAgent; @@ -55,7 +53,6 @@ function isMobileSafari() { /** * Checks if requesting user agent is Chrome browser on a mobile device * - * @returns {Boolean} */ function isMobileChrome() { const userAgent = navigator.userAgent; @@ -68,8 +65,6 @@ function isSafari() { /** * The session information needs to be passed to the Desktop app, and the only way to do that is by using query params. There is no other way to transfer the data. - * @param {String} shortLivedAuthToken - * @param {String} email */ function openRouteInDesktopApp(shortLivedAuthToken = '', email = '') { const params = new URLSearchParams(); @@ -95,8 +90,9 @@ function openRouteInDesktopApp(shortLivedAuthToken = '', email = '') { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); - iframe.contentWindow.location.href = expensifyDeeplinkUrl; - + if (iframe.contentWindow) { + iframe.contentWindow.location.href = expensifyDeeplinkUrl; + } // Since we're creating an iframe for Safari to handle deeplink, // we need to give Safari some time to open the pop-up window. // After that we can just remove the iframe. diff --git a/src/libs/CollectionUtils.js b/src/libs/CollectionUtils.js deleted file mode 100644 index 3625c68d2c39..000000000000 --- a/src/libs/CollectionUtils.js +++ /dev/null @@ -1,27 +0,0 @@ -import _ from 'underscore'; - -/** - * Return the highest item in a numbered collection - * - * e.g. {1: '1', 2: '2', 3: '3'} -> '3' - * - * @param {Object} object - * @returns {*} - */ -function lastItem(object = {}) { - const lastKey = _.last(_.keys(object)) || 0; - return object[lastKey]; -} - -/** - * Used to grab the id for a particular collection item's key. - * e.g. reportActions_1 -> 1 - * - * @param {String} key - * @returns {String} - */ -function extractCollectionItemID(key) { - return key.split('_')[1]; -} - -export {lastItem, extractCollectionItemID}; diff --git a/src/libs/CollectionUtils.ts b/src/libs/CollectionUtils.ts new file mode 100644 index 000000000000..ac47633c2e08 --- /dev/null +++ b/src/libs/CollectionUtils.ts @@ -0,0 +1,23 @@ +import {OnyxCollectionKey} from '../ONYXKEYS'; + +/** + * Return the highest item in a numbered collection + * + * e.g. {1: '1', 2: '2', 3: '3'} -> '3' + * + * Use this only for collections that are numbered in other cases it will return the last item in the object not the highest + */ +function lastItem(object: Record = {}): T | undefined { + const lastKey = Object.keys(object).pop() ?? 0; + return object[lastKey]; +} + +/** + * Used to grab the id for a particular collection item's key. + * e.g. reportActions_1 -> 1 + */ +function extractCollectionItemID(key: `${OnyxCollectionKey}${string}`): string { + return key.split('_')[1]; +} + +export {lastItem, extractCollectionItemID}; diff --git a/src/libs/EmojiTrie.js b/src/libs/EmojiTrie.js index b0bd0d5eec5d..00e5fc1388e1 100644 --- a/src/libs/EmojiTrie.js +++ b/src/libs/EmojiTrie.js @@ -8,6 +8,41 @@ Timing.start(CONST.TIMING.TRIE_INITIALIZATION); const supportedLanguages = [CONST.LOCALES.DEFAULT, CONST.LOCALES.ES]; +/** + * + * @param {Trie} trie The Trie object. + * @param {Array} keywords An array containing the keywords. + * @param {Object} item An object containing the properties of the emoji. + * @param {String} name The localized name of the emoji. + * @param {Boolean} shouldPrependKeyword Prepend the keyword (instead of append) to the suggestions + */ +function addKeywordsToTrie(trie, keywords, item, name, shouldPrependKeyword = false) { + _.forEach(keywords, (keyword) => { + const keywordNode = trie.search(keyword); + if (!keywordNode) { + trie.add(keyword, {suggestions: [{code: item.code, types: item.types, name}]}); + } else { + const suggestion = {code: item.code, types: item.types, name}; + const suggestions = shouldPrependKeyword ? [suggestion, ...keywordNode.metaData.suggestions] : [...keywordNode.metaData.suggestions, suggestion]; + trie.update(keyword, { + ...keywordNode.metaData, + suggestions, + }); + } + }); +} + +/** + * Allows searching based on parts of the name. This turns 'white_large_square' into ['white_large_square', 'large_square', 'square']. + * + * @param {String} name The emoji name + * @returns {Array} An array containing the name parts + */ +function getNameParts(name) { + const nameSplit = name.split('_'); + return _.map(nameSplit, (_namePart, index) => nameSplit.slice(index).join('_')); +} + function createTrie(lang = CONST.LOCALES.DEFAULT) { const trie = new Trie(); const langEmojis = localeEmojis[lang]; @@ -28,32 +63,20 @@ function createTrie(lang = CONST.LOCALES.DEFAULT) { trie.update(localeName, {code: item.code, types: item.types, name: localeName, suggestions: node.metaData.suggestions}); } + const nameParts = getNameParts(localeName).slice(1); // We remove the first part because we already index the full name. + addKeywordsToTrie(trie, nameParts, item, localeName); + // Add keywords for both the locale language and English to enable users to search using either language. const keywords = _.get(langEmojis, [item.code, 'keywords'], []).concat(isDefaultLocale ? [] : _.get(localeEmojis, [CONST.LOCALES.DEFAULT, item.code, 'keywords'], [])); - for (let j = 0; j < keywords.length; j++) { - const keywordNode = trie.search(keywords[j]); - if (!keywordNode) { - trie.add(keywords[j], {suggestions: [{code: item.code, types: item.types, name: localeName}]}); - } else { - trie.update(keywords[j], { - ...keywordNode.metaData, - suggestions: [...keywordNode.metaData.suggestions, {code: item.code, types: item.types, name: localeName}], - }); - } - } + addKeywordsToTrie(trie, keywords, item, localeName); - // If current language isn't the default, prepend the English name of the emoji in the suggestions as well. - // We do this because when the user types the english name of the emoji, we want to show the emoji in the suggestions before all the others. + /** + * If current language isn't the default, prepend the English name of the emoji in the suggestions as well. + * We do this because when the user types the english name of the emoji, we want to show the emoji in the suggestions before all the others. + */ if (!isDefaultLocale) { - const englishNode = trie.search(englishName); - if (!englishNode) { - trie.add(englishName, {suggestions: [{code: item.code, types: item.types, name: localeName}]}); - } else { - trie.update(englishName, { - ...englishNode.metaData, - suggestions: [{code: item.code, types: item.types, name: localeName}, ...englishNode.metaData.suggestions], - }); - } + const englishNameParts = getNameParts(englishName); + addKeywordsToTrie(trie, englishNameParts, item, localeName, true); } }); diff --git a/src/libs/GetStyledTextArray.js b/src/libs/GetStyledTextArray.ts similarity index 86% rename from src/libs/GetStyledTextArray.js rename to src/libs/GetStyledTextArray.ts index 576e6f98c94b..cdcedbac2a4f 100644 --- a/src/libs/GetStyledTextArray.js +++ b/src/libs/GetStyledTextArray.ts @@ -1,12 +1,11 @@ import Str from 'expensify-common/lib/str'; -/** - * Render a suggestion menu item component. - * @param {String} name - * @param {String} prefix - * @returns {Array} - */ -const getStyledTextArray = (name, prefix) => { +type StyledText = { + text: string; + isColored: boolean; +}; + +const getStyledTextArray = (name: string, prefix: string): StyledText[] => { const texts = []; const prefixLowercase = prefix.toLowerCase(); const prefixLocation = name.toLowerCase().search(Str.escapeForRegExp(prefixLowercase)); diff --git a/src/libs/GooglePlacesUtils.js b/src/libs/GooglePlacesUtils.js deleted file mode 100644 index 8723598264fb..000000000000 --- a/src/libs/GooglePlacesUtils.js +++ /dev/null @@ -1,51 +0,0 @@ -import _ from 'underscore'; - -/** - * Finds an address component by type, and returns the value associated to key. Each address component object - * inside the addressComponents array has the following structure: - * [{ - * long_name: "New York", - * short_name: "New York", - * types: [ "locality", "political" ] - * }] - * - * @param {Array} addressComponents - * @param {Object} fieldsToExtract – has shape: {addressType: 'keyToUse'} - * @returns {Object} - */ -function getAddressComponents(addressComponents, fieldsToExtract) { - const result = _.mapObject(fieldsToExtract, () => ''); - _.each(addressComponents, (addressComponent) => { - _.each(addressComponent.types, (addressType) => { - if (!_.has(fieldsToExtract, addressType) || !_.isEmpty(result[addressType])) { - return; - } - const value = addressComponent[fieldsToExtract[addressType]] ? addressComponent[fieldsToExtract[addressType]] : ''; - result[addressType] = value; - }); - }); - return result; -} - -/** - * Finds an address term by type, and returns the value associated to key. Note that each term in the address must - * conform to the following ORDER: - * - * @param {Array} addressTerms - * @returns {Object} - */ -function getPlaceAutocompleteTerms(addressTerms) { - const fieldsToExtract = ['country', 'state', 'city', 'street']; - const result = {}; - _.each(fieldsToExtract, (fieldToExtract, index) => { - const fieldTermIndex = addressTerms.length - (index + 1); - result[fieldToExtract] = fieldTermIndex >= 0 ? addressTerms[fieldTermIndex].value : ''; - }); - return result; -} - -export { - // eslint-disable-next-line import/prefer-default-export - getAddressComponents, - getPlaceAutocompleteTerms, -}; diff --git a/src/libs/GooglePlacesUtils.ts b/src/libs/GooglePlacesUtils.ts new file mode 100644 index 000000000000..43fac2b9a785 --- /dev/null +++ b/src/libs/GooglePlacesUtils.ts @@ -0,0 +1,53 @@ +type AddressComponent = { + // eslint-disable-next-line @typescript-eslint/naming-convention + long_name: string; + // eslint-disable-next-line @typescript-eslint/naming-convention + short_name: string; + types: string[]; +}; +type FieldsToExtract = Record>; + +/** + * Finds an address component by type, and returns the value associated to key. Each address component object + * inside the addressComponents array has the following structure: + * [{ + * long_name: "New York", + * short_name: "New York", + * types: [ "locality", "political" ] + * }] + */ +function getAddressComponents(addressComponents: AddressComponent[], fieldsToExtract: FieldsToExtract): Record { + const result: Record = {}; + Object.keys(fieldsToExtract).forEach((key) => (result[key] = '')); + + addressComponents.forEach((addressComponent) => { + addressComponent.types.forEach((addressType) => { + if (!(addressType in fieldsToExtract) || !(addressType in result && result[addressType] === '')) { + return; + } + const value = addressComponent[fieldsToExtract[addressType]] ? addressComponent[fieldsToExtract[addressType]] : ''; + result[addressType] = value; + }); + }); + return result; +} + +type AddressTerm = {value: string}; +type GetPlaceAutocompleteTermsResultKey = 'country' | 'state' | 'city' | 'street'; +type GetPlaceAutocompleteTermsResult = Partial>; + +/** + * Finds an address term by type, and returns the value associated to key. Note that each term in the address must + * conform to the following ORDER: + */ +function getPlaceAutocompleteTerms(addressTerms: AddressTerm[]): GetPlaceAutocompleteTermsResult { + const fieldsToExtract: GetPlaceAutocompleteTermsResultKey[] = ['country', 'state', 'city', 'street']; + const result: GetPlaceAutocompleteTermsResult = {}; + fieldsToExtract.forEach((fieldToExtract, index) => { + const fieldTermIndex = addressTerms.length - (index + 1); + result[fieldToExtract] = fieldTermIndex >= 0 ? addressTerms[fieldTermIndex].value : ''; + }); + return result; +} + +export {getAddressComponents, getPlaceAutocompleteTerms}; diff --git a/src/libs/Growl.js b/src/libs/Growl.js deleted file mode 100644 index 81994dd4c255..000000000000 --- a/src/libs/Growl.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import CONST from '../CONST'; - -const growlRef = React.createRef(); -let resolveIsReadyPromise; -const isReadyPromise = new Promise((resolve) => { - resolveIsReadyPromise = resolve; -}); - -function setIsReady() { - resolveIsReadyPromise(); -} - -/** - * Show the growl notification - * - * @param {String} bodyText - * @param {String} type - * @param {Number} [duration] - */ -function show(bodyText, type, duration = CONST.GROWL.DURATION) { - isReadyPromise.then(() => growlRef.current.show(bodyText, type, duration)); -} - -/** - * Show error growl - * - * @param {String} bodyText - * @param {Number} [duration] - */ -function error(bodyText, duration = CONST.GROWL.DURATION) { - show(bodyText, CONST.GROWL.ERROR, duration); -} - -/** - * Show success growl - * - * @param {String} bodyText - * @param {Number} [duration] - */ -function success(bodyText, duration = CONST.GROWL.DURATION) { - show(bodyText, CONST.GROWL.SUCCESS, duration); -} - -export default { - show, - error, - success, -}; - -export {growlRef, setIsReady}; diff --git a/src/libs/Growl.ts b/src/libs/Growl.ts new file mode 100644 index 000000000000..99c728f0a210 --- /dev/null +++ b/src/libs/Growl.ts @@ -0,0 +1,49 @@ +import React from 'react'; +import CONST from '../CONST'; + +type GrowlRef = { + show?: (bodyText: string, type: string, duration: number) => void; +}; + +const growlRef = React.createRef(); +let resolveIsReadyPromise: undefined | ((value?: unknown) => void); +const isReadyPromise = new Promise((resolve) => { + resolveIsReadyPromise = resolve; +}); + +function setIsReady() { + if (!resolveIsReadyPromise) return; + resolveIsReadyPromise(); +} + +/** + * Show the growl notification + */ +function show(bodyText: string, type: string, duration: number = CONST.GROWL.DURATION) { + isReadyPromise.then(() => { + if (!growlRef?.current?.show) return; + growlRef.current.show(bodyText, type, duration); + }); +} + +/** + * Show error growl + */ +function error(bodyText: string, duration: number = CONST.GROWL.DURATION) { + show(bodyText, CONST.GROWL.ERROR, duration); +} + +/** + * Show success growl + */ +function success(bodyText: string, duration: number = CONST.GROWL.DURATION) { + show(bodyText, CONST.GROWL.SUCCESS, duration); +} + +export default { + show, + error, + success, +}; + +export {growlRef, setIsReady}; diff --git a/src/libs/HapticFeedback/index.native.js b/src/libs/HapticFeedback/index.native.js deleted file mode 100644 index bc57c74d8d04..000000000000 --- a/src/libs/HapticFeedback/index.native.js +++ /dev/null @@ -1,32 +0,0 @@ -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; - -function press() { - ReactNativeHapticFeedback.trigger('impactLight', { - enableVibrateFallback: true, - }); -} - -function longPress() { - ReactNativeHapticFeedback.trigger('impactHeavy', { - enableVibrateFallback: true, - }); -} - -function success() { - ReactNativeHapticFeedback.trigger('notificationSuccess', { - enableVibrateFallback: true, - }); -} - -function error() { - ReactNativeHapticFeedback.trigger('notificationError', { - enableVibrateFallback: true, - }); -} - -export default { - press, - longPress, - success, - error, -}; diff --git a/src/libs/HapticFeedback/index.native.ts b/src/libs/HapticFeedback/index.native.ts new file mode 100644 index 000000000000..4c3605cc27ef --- /dev/null +++ b/src/libs/HapticFeedback/index.native.ts @@ -0,0 +1,27 @@ +import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; +import HapticFeedback from './types'; + +const hapticFeedback: HapticFeedback = { + press: () => { + ReactNativeHapticFeedback.trigger('impactLight', { + enableVibrateFallback: true, + }); + }, + longPress: () => { + ReactNativeHapticFeedback.trigger('impactHeavy', { + enableVibrateFallback: true, + }); + }, + success: () => { + ReactNativeHapticFeedback.trigger('notificationSuccess', { + enableVibrateFallback: true, + }); + }, + error: () => { + ReactNativeHapticFeedback.trigger('notificationError', { + enableVibrateFallback: true, + }); + }, +}; + +export default hapticFeedback; diff --git a/src/libs/HapticFeedback/index.js b/src/libs/HapticFeedback/index.ts similarity index 55% rename from src/libs/HapticFeedback/index.js rename to src/libs/HapticFeedback/index.ts index cef9f994ddaf..3dd5b87f573b 100644 --- a/src/libs/HapticFeedback/index.js +++ b/src/libs/HapticFeedback/index.ts @@ -1,9 +1,13 @@ +import HapticFeedback from './types'; + /** * Web does not support Haptic feedback */ -export default { +const hapticFeedback: HapticFeedback = { press: () => {}, longPress: () => {}, success: () => {}, error: () => {}, }; + +export default hapticFeedback; diff --git a/src/libs/HapticFeedback/types.ts b/src/libs/HapticFeedback/types.ts new file mode 100644 index 000000000000..3db056fad148 --- /dev/null +++ b/src/libs/HapticFeedback/types.ts @@ -0,0 +1,8 @@ +type HapticFeedback = { + press: () => void; + longPress: () => void; + success: () => void; + error: () => void; +}; + +export default HapticFeedback; diff --git a/src/libs/IntlPolyfill/index.js b/src/libs/IntlPolyfill/index.js index 3925b98729a9..a99fc4cfed44 100644 --- a/src/libs/IntlPolyfill/index.js +++ b/src/libs/IntlPolyfill/index.js @@ -7,4 +7,5 @@ import polyfillNumberFormat from './polyfillNumberFormat'; export default function intlPolyfill() { // Just need to polyfill Intl.NumberFormat for web based platforms polyfillNumberFormat(); + require('@formatjs/intl-datetimeformat'); } diff --git a/src/libs/IntlPolyfill/index.native.js b/src/libs/IntlPolyfill/index.native.js index a628654fefea..4fb5ca585e25 100644 --- a/src/libs/IntlPolyfill/index.native.js +++ b/src/libs/IntlPolyfill/index.native.js @@ -9,6 +9,7 @@ export default function polyfill() { require('@formatjs/intl-getcanonicallocales/polyfill'); require('@formatjs/intl-locale/polyfill'); require('@formatjs/intl-pluralrules/polyfill'); + require('@formatjs/intl-datetimeformat'); polyfillNumberFormat(); polyfillListFormat(); } diff --git a/src/libs/LocaleDigitUtils.js b/src/libs/LocaleDigitUtils.ts similarity index 68% rename from src/libs/LocaleDigitUtils.js rename to src/libs/LocaleDigitUtils.ts index 23396f8d2fb6..e17620aa5427 100644 --- a/src/libs/LocaleDigitUtils.js +++ b/src/libs/LocaleDigitUtils.ts @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import _ from 'lodash'; import * as NumberFormatUtils from './NumberFormatUtils'; @@ -8,12 +8,12 @@ const INDEX_DECIMAL = 10; const INDEX_MINUS_SIGN = 11; const INDEX_GROUP = 12; -const getLocaleDigits = _.memoize((locale) => { - const localeDigits = _.clone(STANDARD_DIGITS); +const getLocaleDigits = _.memoize((locale: string): string[] => { + const localeDigits = [...STANDARD_DIGITS]; for (let i = 0; i <= 9; i++) { localeDigits[i] = NumberFormatUtils.format(locale, i); } - _.forEach(NumberFormatUtils.formatToParts(locale, 1000000.5), (part) => { + NumberFormatUtils.formatToParts(locale, 1000000.5).forEach((part) => { switch (part.type) { case 'decimal': localeDigits[INDEX_DECIMAL] = part.value; @@ -34,15 +34,13 @@ const getLocaleDigits = _.memoize((locale) => { /** * Gets the locale digit corresponding to a standard digit. * - * @param {String} locale - * @param {String} digit - Character of a single standard digit . It may be "0" ~ "9" (digits), + * @param digit - Character of a single standard digit . It may be "0" ~ "9" (digits), * "," (group separator), "." (decimal separator) or "-" (minus sign). - * @returns {String} * * @throws If `digit` is not a valid standard digit. */ -function toLocaleDigit(locale, digit) { - const index = _.indexOf(STANDARD_DIGITS, digit); +function toLocaleDigit(locale: string, digit: string): string { + const index = STANDARD_DIGITS.indexOf(digit); if (index < 0) { throw new Error(`"${digit}" must be in ${JSON.stringify(STANDARD_DIGITS)}`); } @@ -52,15 +50,13 @@ function toLocaleDigit(locale, digit) { /** * Gets the standard digit corresponding to a locale digit. * - * @param {String} locale - * @param {String} localeDigit - Character of a single locale digit. It may be **the localized version** of + * @param localeDigit - Character of a single locale digit. It may be **the localized version** of * "0" ~ "9" (digits), "," (group separator), "." (decimal separator) or "-" (minus sign). - * @returns {String} * * @throws If `localeDigit` is not a valid locale digit. */ -function fromLocaleDigit(locale, localeDigit) { - const index = _.indexOf(getLocaleDigits(locale), localeDigit); +function fromLocaleDigit(locale: string, localeDigit: string): string { + const index = getLocaleDigits(locale).indexOf(localeDigit); if (index < 0) { throw new Error(`"${localeDigit}" must be in ${JSON.stringify(getLocaleDigits(locale))}`); } diff --git a/src/libs/Localize/index.js b/src/libs/Localize/index.js index 9878873377b8..db371301f43f 100644 --- a/src/libs/Localize/index.js +++ b/src/libs/Localize/index.js @@ -38,7 +38,7 @@ function init() { * Return translated string for given locale and phrase * * @param {String} [desiredLanguage] eg 'en', 'es-ES' - * @param {String|Array} phraseKey + * @param {String} phraseKey * @param {Object} [phraseParameters] Parameters to supply if the phrase is a template literal. * @returns {String} */ @@ -47,15 +47,15 @@ function translate(desiredLanguage = CONST.LOCALES.DEFAULT, phraseKey, phrasePar let translatedPhrase; // Search phrase in full locale e.g. es-ES - const desiredLanguageDictionary = lodashGet(translations, desiredLanguage); - translatedPhrase = lodashGet(desiredLanguageDictionary, phraseKey); + const desiredLanguageDictionary = translations[desiredLanguage] || {}; + translatedPhrase = desiredLanguageDictionary[phraseKey]; if (translatedPhrase) { return Str.result(translatedPhrase, phraseParameters); } // Phrase is not found in full locale, search it in fallback language e.g. es - const fallbackLanguageDictionary = lodashGet(translations, languageAbbreviation); - translatedPhrase = lodashGet(fallbackLanguageDictionary, phraseKey); + const fallbackLanguageDictionary = translations[languageAbbreviation] || {}; + translatedPhrase = fallbackLanguageDictionary[phraseKey]; if (translatedPhrase) { return Str.result(translatedPhrase, phraseParameters); } @@ -64,8 +64,8 @@ function translate(desiredLanguage = CONST.LOCALES.DEFAULT, phraseKey, phrasePar } // Phrase is not translated, search it in default language (en) - const defaultLanguageDictionary = lodashGet(translations, CONST.LOCALES.DEFAULT, {}); - translatedPhrase = lodashGet(defaultLanguageDictionary, phraseKey); + const defaultLanguageDictionary = translations[CONST.LOCALES.DEFAULT] || {}; + translatedPhrase = defaultLanguageDictionary[phraseKey]; if (translatedPhrase) { return Str.result(translatedPhrase, phraseParameters); } diff --git a/src/libs/Metrics/index.js b/src/libs/Metrics/index.js deleted file mode 100644 index 2c90f1c51b65..000000000000 --- a/src/libs/Metrics/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from '../../CONFIG'; - -// We don't capture performance metrics on web as there are enough tools available -const canCapturePerformanceMetrics = () => false; - -const canCaptureOnyxMetrics = () => Boolean(CONFIG.ONYX_METRICS); - -export {canCapturePerformanceMetrics, canCaptureOnyxMetrics}; diff --git a/src/libs/Metrics/index.native.js b/src/libs/Metrics/index.native.js deleted file mode 100644 index f57526e674ba..000000000000 --- a/src/libs/Metrics/index.native.js +++ /dev/null @@ -1,17 +0,0 @@ -import CONFIG from '../../CONFIG'; - -/** - * Is capturing performance stats enabled. - * - * @returns {Boolean} - */ -const canCapturePerformanceMetrics = () => CONFIG.CAPTURE_METRICS; - -/** - * Is capturing Onyx stats enabled. - * - * @returns {Boolean} - */ -const canCaptureOnyxMetrics = () => CONFIG.ONYX_METRICS; - -export {canCapturePerformanceMetrics, canCaptureOnyxMetrics}; diff --git a/src/libs/Metrics/index.native.ts b/src/libs/Metrics/index.native.ts new file mode 100644 index 000000000000..526e5c57a269 --- /dev/null +++ b/src/libs/Metrics/index.native.ts @@ -0,0 +1,14 @@ +import CONFIG from '../../CONFIG'; +import {CanCaptureOnyxMetrics, CanCapturePerformanceMetrics} from './types'; + +/** + * Is capturing performance stats enabled. + */ +const canCapturePerformanceMetrics: CanCapturePerformanceMetrics = () => CONFIG.CAPTURE_METRICS; + +/** + * Is capturing Onyx stats enabled. + */ +const canCaptureOnyxMetrics: CanCaptureOnyxMetrics = () => CONFIG.ONYX_METRICS; + +export {canCapturePerformanceMetrics, canCaptureOnyxMetrics}; diff --git a/src/libs/Metrics/index.ts b/src/libs/Metrics/index.ts new file mode 100644 index 000000000000..7c33f31cb19e --- /dev/null +++ b/src/libs/Metrics/index.ts @@ -0,0 +1,9 @@ +import CONFIG from '../../CONFIG'; +import {CanCaptureOnyxMetrics, CanCapturePerformanceMetrics} from './types'; + +// We don't capture performance metrics on web as there are enough tools available +const canCapturePerformanceMetrics: CanCapturePerformanceMetrics = () => false; + +const canCaptureOnyxMetrics: CanCaptureOnyxMetrics = () => CONFIG.ONYX_METRICS; + +export {canCapturePerformanceMetrics, canCaptureOnyxMetrics}; diff --git a/src/libs/Metrics/types.ts b/src/libs/Metrics/types.ts new file mode 100644 index 000000000000..61b1400ae9f8 --- /dev/null +++ b/src/libs/Metrics/types.ts @@ -0,0 +1,4 @@ +type CanCapturePerformanceMetrics = () => boolean; +type CanCaptureOnyxMetrics = () => boolean; + +export type {CanCapturePerformanceMetrics, CanCaptureOnyxMetrics}; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index e10e51b307e4..37b7087b6ad4 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -1,7 +1,6 @@ import React from 'react'; import Onyx, {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; -import moment from 'moment'; import _ from 'underscore'; import lodashGet from 'lodash/get'; import {View} from 'react-native'; @@ -65,7 +64,7 @@ Onyx.connect({ } timezone = lodashGet(val, [currentAccountID, 'timezone'], {}); - const currentTimezone = moment.tz.guess(true); + const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic // then update their timezone. @@ -106,16 +105,6 @@ const propTypes = { /** The last Onyx update ID was applied to the client */ lastUpdateIDAppliedToClient: PropTypes.number, - /** Information about any currently running demos */ - demoInfo: PropTypes.shape({ - saastr: PropTypes.shape({ - isBeginningDemo: PropTypes.bool, - }), - sbe: PropTypes.shape({ - isBeginningDemo: PropTypes.bool, - }), - }), - ...windowDimensionsPropTypes, }; @@ -126,7 +115,6 @@ const defaultProps = { }, lastOpenedPublicRoomID: null, lastUpdateIDAppliedToClient: null, - demoInfo: {}, }; class AuthScreens extends React.Component { @@ -163,12 +151,6 @@ class AuthScreens extends React.Component { App.setUpPoliciesAndNavigate(this.props.session, !this.props.isSmallScreenWidth); App.redirectThirdPartyDesktopSignIn(); - // Check if we should be running any demos immediately after signing in. - if (lodashGet(this.props.demoInfo, 'saastr.isBeginningDemo', false)) { - Navigation.navigate(ROUTES.SAASTR, CONST.NAVIGATION.TYPE.FORCED_UP); - } else if (lodashGet(this.props.demoInfo, 'sbe.isBeginningDemo', false)) { - Navigation.navigate(ROUTES.SBE, CONST.NAVIGATION.TYPE.FORCED_UP); - } if (this.props.lastOpenedPublicRoomID) { // Re-open the last opened public room if the user logged in from a public room link Report.openLastOpenedPublicRoom(this.props.lastOpenedPublicRoomID); @@ -344,8 +326,5 @@ export default compose( lastUpdateIDAppliedToClient: { key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, }, - demoInfo: { - key: ONYXKEYS.DEMO_INFO, - }, }), )(AuthScreens); diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 2adaf0397a2c..851f7aff3a8d 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -90,6 +90,13 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator([ }, name: 'Money_Request_Category', }, + { + getComponent: () => { + const MoneyRequestTagPage = require('../../../pages/iou/MoneyRequestTagPage').default; + return MoneyRequestTagPage; + }, + name: 'Money_Request_Tag', + }, { getComponent: () => { const MoneyRequestMerchantPage = require('../../../pages/iou/MoneyRequestMerchantPage').default; diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js index 00c2d536e8ba..d8cb96e2c6b3 100644 --- a/src/libs/Navigation/NavigationRoot.js +++ b/src/libs/Navigation/NavigationRoot.js @@ -86,7 +86,12 @@ function NavigationRoot(props) { const updateStatusBarBackgroundColor = (color) => StatusBar.setBackgroundColor(color); useAnimatedReaction( () => statusBarAnimation.value, - () => { + (current, previous) => { + // Do not run if either of the animated value is null + // or previous animated value is greater than or equal to the current one + if ([current, previous].includes(null) || current <= previous) { + return; + } const color = interpolateColor(statusBarAnimation.value, [0, 1], [prevStatusBarBackgroundColor.current, statusBarBackgroundColor.current]); runOnJS(updateStatusBarBackgroundColor)(color); }, diff --git a/src/libs/Navigation/OnyxTabNavigator.js b/src/libs/Navigation/OnyxTabNavigator.js index d1717cc8a481..dc68021bf515 100644 --- a/src/libs/Navigation/OnyxTabNavigator.js +++ b/src/libs/Navigation/OnyxTabNavigator.js @@ -54,6 +54,6 @@ OnyxTabNavigator.displayName = 'OnyxTabNavigator'; export default withOnyx({ selectedTab: { - key: ({id}) => `${ONYXKEYS.SELECTED_TAB}_${id}`, + key: ({id}) => `${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`, }, })(OnyxTabNavigator); diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index ee3054e02f96..62aac8c48e25 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -265,7 +265,7 @@ export default { }, TeachersUnite: { screens: { - SaveTheWorld_Root: ROUTES.SAVE_THE_WORLD, + SaveTheWorld_Root: ROUTES.TEACHERS_UNITE, I_Know_A_Teacher: ROUTES.I_KNOW_A_TEACHER, Intro_School_Principal: ROUTES.INTRO_SCHOOL_PRINCIPAL, I_Am_A_Teacher: ROUTES.I_AM_A_TEACHER, @@ -318,6 +318,7 @@ export default { Money_Request_Currency: ROUTES.MONEY_REQUEST_CURRENCY, Money_Request_Description: ROUTES.MONEY_REQUEST_DESCRIPTION, Money_Request_Category: ROUTES.MONEY_REQUEST_CATEGORY, + Money_Request_Tag: ROUTES.MONEY_REQUEST_TAG, Money_Request_Merchant: ROUTES.MONEY_REQUEST_MERCHANT, Money_Request_Waypoint: ROUTES.MONEY_REQUEST_WAYPOINT, IOU_Send_Enable_Payments: ROUTES.IOU_SEND_ENABLE_PAYMENTS, diff --git a/src/libs/NumberUtils.js b/src/libs/NumberUtils.ts similarity index 80% rename from src/libs/NumberUtils.js rename to src/libs/NumberUtils.ts index ee0b8a8fa397..0d2b4135c5b6 100644 --- a/src/libs/NumberUtils.js +++ b/src/libs/NumberUtils.ts @@ -1,11 +1,11 @@ -import _ from 'underscore'; import CONST from '../CONST'; /** * Generates a random positive 64 bit numeric string by randomly generating the left, middle, and right parts and concatenating them. Used to generate client-side ids. - * @returns {String} string representation of a randomly generated 64 bit signed integer + * + * @returns string representation of a randomly generated 64 bit signed integer */ -function rand64() { +function rand64(): string { // Max 64-bit signed: // 9,223,372,036,854,775,807 // The left part of the max 64-bit number *+1* because we're flooring it. @@ -38,24 +38,22 @@ function rand64() { /** * Returns a hexadecimal value of the specified length - * @param {Number} num - * @returns {String} */ -function generateHexadecimalValue(num) { - return _.times(num, () => Math.floor(Math.random() * 16).toString(16)) - .join('') - .toUpperCase(); +function generateHexadecimalValue(num: number): string { + const result: string[] = []; + for (let i = 0; i < num; i++) { + result.push(Math.floor(Math.random() * 16).toString(16)); + } + return result.join('').toUpperCase(); } /** * Generates a random integer between a and b * It's and equivalent of _.random(a, b) * - * @param {Number} a - * @param {Number} b - * @returns {Number} random integer between a and b + * @returns random integer between a and b */ -function generateRandomInt(a, b) { +function generateRandomInt(a: number, b: number): number { const lower = Math.ceil(Math.min(a, b)); const upper = Math.floor(Math.max(a, b)); return Math.floor(lower + Math.random() * (upper - lower + 1)); diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index d26ad48430b0..7629a1acc0a6 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -652,12 +652,8 @@ function getCategoryOptionTree(options, isOneLine = false) { /** * Build the section list for categories * - * @param {Object[]} categories - * @param {String} categories[].name - * @param {Boolean} categories[].enabled - * @param {Object[]} recentlyUsedCategories - * @param {String} recentlyUsedCategories[].name - * @param {Boolean} recentlyUsedCategories[].enabled + * @param {Object} categories + * @param {String[]} recentlyUsedCategories * @param {Object[]} selectedOptions * @param {String} selectedOptions[].name * @param {String} searchInputValue @@ -666,11 +662,12 @@ function getCategoryOptionTree(options, isOneLine = false) { */ function getCategoryListSections(categories, recentlyUsedCategories, selectedOptions, searchInputValue, maxRecentReportsToShow) { const categorySections = []; - const numberOfCategories = _.size(categories); + const categoriesValues = _.values(categories); + const numberOfCategories = _.size(categoriesValues); let indexOffset = 0; if (!_.isEmpty(searchInputValue)) { - const searchCategories = _.filter(categories, (category) => category.name.toLowerCase().includes(searchInputValue.toLowerCase())); + const searchCategories = _.filter(categoriesValues, (category) => category.name.toLowerCase().includes(searchInputValue.toLowerCase())); categorySections.push({ // "Search" section @@ -689,15 +686,21 @@ function getCategoryListSections(categories, recentlyUsedCategories, selectedOpt title: '', shouldShow: false, indexOffset, - data: getCategoryOptionTree(categories), + data: getCategoryOptionTree(categoriesValues), }); return categorySections; } const selectedOptionNames = _.map(selectedOptions, (selectedOption) => selectedOption.name); - const filteredRecentlyUsedCategories = _.filter(recentlyUsedCategories, (category) => !_.includes(selectedOptionNames, category.name)); - const filteredCategories = _.filter(categories, (category) => !_.includes(selectedOptionNames, category.name)); + const filteredRecentlyUsedCategories = _.map( + _.filter(recentlyUsedCategories, (category) => !_.includes(selectedOptionNames, category)), + (category) => ({ + name: category, + enabled: lodashGet(categories, `${category}.enabled`, false), + }), + ); + const filteredCategories = _.filter(categoriesValues, (category) => !_.includes(selectedOptionNames, category.name)); if (!_.isEmpty(selectedOptions)) { categorySections.push({ @@ -776,7 +779,7 @@ function getOptions( }, ) { if (includeCategories) { - const categoryOptions = getCategoryListSections(_.values(categories), recentlyUsedCategories, selectedOptions, searchInputValue, maxRecentReportsToShow); + const categoryOptions = getCategoryListSections(categories, recentlyUsedCategories, selectedOptions, searchInputValue, maxRecentReportsToShow); return { recentReports: [], @@ -1127,7 +1130,7 @@ function getIOUConfirmationOptionsFromParticipants(participants, amountText) { * @param {boolean} [includeP2P] * @param {boolean} [includeCategories] * @param {Object} [categories] - * @param {Array} [recentlyUsedCategories] + * @param {Array} [recentlyUsedCategories] * @param {boolean} [canInviteUser] * @returns {Object} */ diff --git a/src/libs/Permissions.js b/src/libs/Permissions.js index f37cd5bb5bf3..0294236b1cd7 100644 --- a/src/libs/Permissions.js +++ b/src/libs/Permissions.js @@ -86,6 +86,22 @@ function canUseCustomStatus(betas) { return _.contains(betas, CONST.BETAS.CUSTOM_STATUS) || canUseAllBetas(betas); } +/** + * @param {Array} betas + * @returns {Boolean} + */ +function canUseCategories(betas) { + return _.contains(betas, CONST.BETAS.NEW_DOT_CATEGORIES) || canUseAllBetas(betas); +} + +/** + * @param {Array} betas + * @returns {Boolean} + */ +function canUseTags(betas) { + return _.contains(betas, CONST.BETAS.NEW_DOT_TAGS) || canUseAllBetas(betas); +} + /** * Link previews are temporarily disabled. * @returns {Boolean} @@ -104,5 +120,7 @@ export default { canUsePolicyRooms, canUseTasks, canUseCustomStatus, + canUseCategories, + canUseTags, canUseLinkPreviews, }; diff --git a/src/libs/ReceiptUtils.js b/src/libs/ReceiptUtils.js index f7a53227d8d7..d90a6cbf0e37 100644 --- a/src/libs/ReceiptUtils.js +++ b/src/libs/ReceiptUtils.js @@ -4,7 +4,6 @@ import Str from 'expensify-common/lib/str'; import * as FileUtils from './fileDownload/FileUtils'; import CONST from '../CONST'; import Receipt from './actions/Receipt'; -import * as Localize from './Localize'; import ReceiptHTML from '../../assets/images/receipt-html.png'; import ReceiptDoc from '../../assets/images/receipt-doc.png'; import ReceiptGeneric from '../../assets/images/receipt-generic.png'; @@ -13,17 +12,17 @@ import ReceiptSVG from '../../assets/images/receipt-svg.png'; function validateReceipt(file) { const {fileExtension} = FileUtils.splitExtensionFromFileName(lodashGet(file, 'name', '')); if (_.contains(CONST.API_ATTACHMENT_VALIDATIONS.UNALLOWED_EXTENSIONS, fileExtension.toLowerCase())) { - Receipt.setUploadReceiptError(true, Localize.translateLocal('attachmentPicker.wrongFileType'), Localize.translateLocal('attachmentPicker.notAllowedExtension')); + Receipt.setUploadReceiptError(true, 'attachmentPicker.wrongFileType', 'attachmentPicker.notAllowedExtension'); return false; } if (lodashGet(file, 'size', 0) > CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE) { - Receipt.setUploadReceiptError(true, Localize.translateLocal('attachmentPicker.attachmentTooLarge'), Localize.translateLocal('attachmentPicker.sizeExceeded')); + Receipt.setUploadReceiptError(true, 'attachmentPicker.attachmentTooLarge', 'attachmentPicker.sizeExceeded'); return false; } if (lodashGet(file, 'size', 0) < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) { - Receipt.setUploadReceiptError(true, Localize.translateLocal('attachmentPicker.attachmentTooSmall'), Localize.translateLocal('attachmentPicker.sizeNotMet')); + Receipt.setUploadReceiptError(true, 'attachmentPicker.attachmentTooSmall', 'attachmentPicker.sizeNotMet'); return false; } diff --git a/src/libs/ReportActionComposeFocusManager.js b/src/libs/ReportActionComposeFocusManager.ts similarity index 65% rename from src/libs/ReportActionComposeFocusManager.js rename to src/libs/ReportActionComposeFocusManager.ts index 7f31b17aaa57..83493ed71fc5 100644 --- a/src/libs/ReportActionComposeFocusManager.js +++ b/src/libs/ReportActionComposeFocusManager.ts @@ -1,20 +1,21 @@ -import _ from 'underscore'; import React from 'react'; +import {TextInput} from 'react-native'; -const composerRef = React.createRef(); +type FocusCallback = () => void; + +const composerRef = React.createRef(); // There are two types of composer: general composer (edit composer) and main composer. // The general composer callback will take priority if it exists. -let focusCallback = null; -let mainComposerFocusCallback = null; +let focusCallback: FocusCallback | null = null; +let mainComposerFocusCallback: FocusCallback | null = null; /** * Register a callback to be called when focus is requested. * Typical uses of this would be call the focus on the ReportActionComposer. * - * @param {Function} callback callback to register - * @param {Boolean} isMainComposer + * @param callback callback to register */ -function onComposerFocus(callback, isMainComposer = false) { +function onComposerFocus(callback: FocusCallback, isMainComposer = false) { if (isMainComposer) { mainComposerFocusCallback = callback; } else { @@ -24,11 +25,10 @@ function onComposerFocus(callback, isMainComposer = false) { /** * Request focus on the ReportActionComposer - * */ function focus() { - if (!_.isFunction(focusCallback)) { - if (!_.isFunction(mainComposerFocusCallback)) { + if (typeof focusCallback !== 'function') { + if (typeof mainComposerFocusCallback !== 'function') { return; } @@ -41,8 +41,6 @@ function focus() { /** * Clear the registered focus callback - * - * @param {Boolean} isMainComposer */ function clear(isMainComposer = false) { if (isMainComposer) { @@ -54,10 +52,9 @@ function clear(isMainComposer = false) { /** * Exposes the current focus state of the report action composer. - * @return {Boolean} isFocused */ -function isFocused() { - return composerRef.current && composerRef.current.isFocused(); +function isFocused(): boolean { + return !!composerRef.current?.isFocused(); } export default { diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 9bb365c0f42a..20337bd9802f 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -370,7 +370,10 @@ function shouldReportActionBeVisibleAsLastAction(reportAction) { return false; } - return shouldReportActionBeVisible(reportAction, reportAction.reportActionID) && !isWhisperAction(reportAction) && !isDeletedAction(reportAction); + // If a whisper action is the REPORTPREVIEW action, we are displaying it. + return ( + shouldReportActionBeVisible(reportAction, reportAction.reportActionID) && !(isWhisperAction(reportAction) && !isReportPreviewAction(reportAction)) && !isDeletedAction(reportAction) + ); } /** @@ -401,7 +404,7 @@ function getLastVisibleMessage(reportID, actionsToMerge = {}) { if (isReportMessageAttachment(message)) { return { lastMessageTranslationKey: CONST.TRANSLATION_KEYS.ATTACHMENT, - lastMessageText: CONST.TRANSLATION_KEYS.ATTACHMENT, + lastMessageText: CONST.ATTACHMENT_MESSAGE_TEXT, lastMessageHtml: CONST.TRANSLATION_KEYS.ATTACHMENT, }; } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 53423e8deaf2..3b3f7b976ba6 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -126,12 +126,6 @@ function getPolicyName(report, returnEmptyIfNotFound = false, policy = undefined // since they can also be accessed by people who aren't in the workspace const policyName = lodashGet(finalPolicy, 'name') || report.policyName || report.oldPolicyName || noPolicyFound; - // The SBE and SAASTR policies have the user name in its name, however, we do not want to show that - if (lodashGet(finalPolicy, 'owner') === CONST.EMAIL.SBE || lodashGet(finalPolicy, 'owner') === CONST.EMAIL.SAASTR) { - const policyNameParts = policyName.split(' '); - if (!Str.isValidEmail(policyNameParts[0])) return policyName; - return policyNameParts.length > 1 ? policyNameParts.slice(1).join(' ') : policyName; - } return policyName; } @@ -1292,6 +1286,7 @@ function getTransactionDetails(transaction) { currency: TransactionUtils.getCurrency(transaction), comment: TransactionUtils.getDescription(transaction), merchant: TransactionUtils.getMerchant(transaction), + category: TransactionUtils.getCategory(transaction), }; } @@ -1405,6 +1400,10 @@ function getTransactionReportName(reportAction) { return Localize.translateLocal('iou.receiptScanning'); } + if (TransactionUtils.hasMissingSmartscanFields(transaction)) { + return Localize.translateLocal('iou.receiptMissingDetails'); + } + const {amount, currency, comment} = getTransactionDetails(transaction); return Localize.translateLocal(ReportActionsUtils.isSentMoneyReportAction(reportAction) ? 'iou.threadSentMoneyReportName' : 'iou.threadRequestReportName', { @@ -1417,7 +1416,7 @@ function getTransactionReportName(reportAction) { * Get money request message for an IOU report * * @param {Object} report - * @param {Object} [reportAction={}] + * @param {Object} [reportAction={}] This can be either a report preview action or the IOU action * @param {Boolean} [shouldConsiderReceiptBeingScanned=false] * @returns {String} */ @@ -1447,12 +1446,15 @@ function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceip } if (isSettled(report.reportID)) { - // A settled report preview message can come in three formats "paid ... using Paypal.me", "paid ... elsewhere" or "paid ... using Expensify" + // A settled report preview message can come in three formats "paid ... using Paypal.me", "paid ... elsewhere" or "paid ... with Expensify" let translatePhraseKey = 'iou.paidElsewhereWithAmount'; - if (reportActionMessage.match(/ Paypal.me$/)) { + if (reportAction.originalMessage.paymentType === CONST.IOU.PAYMENT_TYPE.PAYPAL_ME || reportActionMessage.match(/ PayPal.me$/)) { translatePhraseKey = 'iou.paidUsingPaypalWithAmount'; - } else if (reportActionMessage.match(/ using Expensify$/)) { - translatePhraseKey = 'iou.paidUsingExpensifyWithAmount'; + } else if ( + _.contains([CONST.IOU.PAYMENT_TYPE.VBBA, CONST.IOU.PAYMENT_TYPE.EXPENSIFY], reportAction.originalMessage.paymentType) || + reportActionMessage.match(/ (with Expensify|using Expensify)$/) + ) { + translatePhraseKey = 'iou.paidWithExpensifyWithAmount'; } return Localize.translateLocal(translatePhraseKey, {amount: formattedAmount}); } @@ -1478,14 +1480,15 @@ function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceip function getProperSchemaForModifiedExpenseMessage(newValue, oldValue, valueName, valueInQuotes) { const newValueToDisplay = valueInQuotes ? `"${newValue}"` : newValue; const oldValueToDisplay = valueInQuotes ? `"${oldValue}"` : oldValue; + const displayValueName = valueName.toLowerCase(); if (!oldValue) { - return `set the ${valueName} to ${newValueToDisplay}`; + return Localize.translateLocal('iou.setTheRequest', {valueName: displayValueName, newValueToDisplay}); } if (!newValue) { - return `removed the ${valueName} (previously ${oldValueToDisplay})`; + return Localize.translateLocal('iou.removedTheRequest', {valueName: displayValueName, oldValueToDisplay}); } - return `changed the ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`; + return Localize.translateLocal('iou.updatedTheRequest', {valueName: displayValueName, newValueToDisplay, oldValueToDisplay}); } /** @@ -1497,7 +1500,7 @@ function getProperSchemaForModifiedExpenseMessage(newValue, oldValue, valueName, function getModifiedExpenseMessage(reportAction) { const reportActionOriginalMessage = lodashGet(reportAction, 'originalMessage', {}); if (_.isEmpty(reportActionOriginalMessage)) { - return `changed the request`; + return Localize.translateLocal('iou.changedTheRequest'); } const hasModifiedAmount = @@ -1512,12 +1515,12 @@ function getModifiedExpenseMessage(reportAction) { const currency = reportActionOriginalMessage.currency; const amount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage.amount, currency); - return getProperSchemaForModifiedExpenseMessage(amount, oldAmount, 'amount', false); + return getProperSchemaForModifiedExpenseMessage(amount, oldAmount, Localize.translateLocal('iou.amount'), false); } const hasModifiedComment = _.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment'); if (hasModifiedComment) { - return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.newComment, reportActionOriginalMessage.oldComment, 'description', true); + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.newComment, reportActionOriginalMessage.oldComment, Localize.translateLocal('common.description'), true); } const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created'); @@ -1525,12 +1528,12 @@ function getModifiedExpenseMessage(reportAction) { // Take only the YYYY-MM-DD value as the original date includes timestamp let formattedOldCreated = parseISO(reportActionOriginalMessage.oldCreated); formattedOldCreated = format(formattedOldCreated, CONST.DATE.FNS_FORMAT_STRING); - return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.created, formattedOldCreated, 'date', false); + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.created, formattedOldCreated, Localize.translateLocal('common.date'), false); } const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant'); if (hasModifiedMerchant) { - return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.merchant, reportActionOriginalMessage.oldMerchant, 'merchant', true); + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.merchant, reportActionOriginalMessage.oldMerchant, Localize.translateLocal('common.merchant'), true); } } @@ -1950,6 +1953,7 @@ function buildOptimisticIOUReport(payeeAccountID, payerAccountID, total, chatRep // We don't translate reportName because the server response is always in English reportName: `${payerEmail} owes ${formattedTotal}`, + parentReportID: chatReportID, }; } @@ -1987,6 +1991,7 @@ function buildOptimisticExpenseReport(chatReportID, policyID, payeeAccountID, to state: CONST.REPORT.STATE.SUBMITTED, stateNum: CONST.REPORT.STATE_NUM.PROCESSING, total: storedTotal, + parentReportID: chatReportID, }; } @@ -2012,7 +2017,8 @@ function getIOUReportActionMessage(iouReportID, type, total, comment, currency, paymentMethodMessage = ' elsewhere'; break; case CONST.IOU.PAYMENT_TYPE.VBBA: - paymentMethodMessage = ' using Expensify'; + case CONST.IOU.PAYMENT_TYPE.EXPENSIFY: + paymentMethodMessage = ' with Expensify'; break; default: paymentMethodMessage = ` using ${paymentType}`; @@ -2621,7 +2627,7 @@ function buildTransactionThread(reportAction, moneyRequestReportID) { participantAccountIDs, getTransactionReportName(reportAction), '', - lodashGet(getReport(reportAction.reportID), 'policyID', CONST.POLICY.OWNER_EMAIL_FAKE), + lodashGet(getReport(moneyRequestReportID), 'policyID', CONST.POLICY.OWNER_EMAIL_FAKE), CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, false, '', @@ -3103,8 +3109,8 @@ function getMoneyRequestOptions(report, reportParticipants, betas) { return []; } - // Additional requests should be blocked for money request reports - if (isMoneyRequestReport(report)) { + // Additional requests should be blocked for money request reports if it is approved or reimbursed + if (isMoneyRequestReport(report) && (isReportApproved(report) || isSettled(report.reportID))) { return []; } diff --git a/src/libs/RequestThrottle.js b/src/libs/RequestThrottle.ts similarity index 64% rename from src/libs/RequestThrottle.js rename to src/libs/RequestThrottle.ts index 4725a3ad5c38..8f9a85dcedb5 100644 --- a/src/libs/RequestThrottle.js +++ b/src/libs/RequestThrottle.ts @@ -1,5 +1,5 @@ -import _ from 'underscore'; import CONST from '../CONST'; +import {generateRandomInt} from './NumberUtils'; let requestWaitTime = 0; @@ -7,22 +7,16 @@ function clear() { requestWaitTime = 0; } -/** - * @returns {Number} time to wait in ms - */ function getRequestWaitTime() { if (requestWaitTime) { requestWaitTime = Math.min(requestWaitTime * 2, CONST.NETWORK.MAX_RETRY_WAIT_TIME_MS); } else { - requestWaitTime = _.random(CONST.NETWORK.MIN_RETRY_WAIT_TIME_MS, CONST.NETWORK.MAX_RANDOM_RETRY_WAIT_TIME_MS); + requestWaitTime = generateRandomInt(CONST.NETWORK.MIN_RETRY_WAIT_TIME_MS, CONST.NETWORK.MAX_RANDOM_RETRY_WAIT_TIME_MS); } return requestWaitTime; } -/** - * @returns {Promise} - */ -function sleep() { +function sleep(): Promise { return new Promise((resolve) => setTimeout(resolve, getRequestWaitTime())); } diff --git a/src/libs/StartupTimer/index.js b/src/libs/StartupTimer/index.js deleted file mode 100644 index 7b53266e50d9..000000000000 --- a/src/libs/StartupTimer/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Web noop as there is no "startup" to time from the native layer. - */ - -export default { - stop() {}, -}; diff --git a/src/libs/StartupTimer/index.native.js b/src/libs/StartupTimer/index.native.js deleted file mode 100644 index 29bbef8cfe3d..000000000000 --- a/src/libs/StartupTimer/index.native.js +++ /dev/null @@ -1,12 +0,0 @@ -import {NativeModules} from 'react-native'; - -/** - * Stop the startup trace for the app. - */ -function stop() { - NativeModules.StartupTimer.stop(); -} - -export default { - stop, -}; diff --git a/src/libs/StartupTimer/index.native.ts b/src/libs/StartupTimer/index.native.ts new file mode 100644 index 000000000000..52ba55076fc1 --- /dev/null +++ b/src/libs/StartupTimer/index.native.ts @@ -0,0 +1,13 @@ +import {NativeModules} from 'react-native'; +import StartupTimer from './types'; + +/** + * Stop the startup trace for the app. + */ +const startupTimer: StartupTimer = { + stop: () => { + NativeModules.StartupTimer.stop(); + }, +}; + +export default startupTimer; diff --git a/src/libs/StartupTimer/index.ts b/src/libs/StartupTimer/index.ts new file mode 100644 index 000000000000..421524a70fc8 --- /dev/null +++ b/src/libs/StartupTimer/index.ts @@ -0,0 +1,11 @@ +/** + * Web noop as there is no "startup" to time from the native layer. + */ + +import StartupTimer from './types'; + +const startupTimer: StartupTimer = { + stop: () => {}, +}; + +export default startupTimer; diff --git a/src/libs/StartupTimer/types.ts b/src/libs/StartupTimer/types.ts new file mode 100644 index 000000000000..e382fc267933 --- /dev/null +++ b/src/libs/StartupTimer/types.ts @@ -0,0 +1,5 @@ +type StartupTimer = { + stop: () => void; +}; + +export default StartupTimer; diff --git a/src/libs/StringUtils.js b/src/libs/StringUtils.js deleted file mode 100644 index 8219f9e8077f..000000000000 --- a/src/libs/StringUtils.js +++ /dev/null @@ -1,12 +0,0 @@ -import _ from 'lodash'; -import CONST from '../CONST'; -/** - * Removes diacritical marks and non-alphabetic and non-latin characters from a string. - * @param {String} str - The input string to be sanitized. - * @returns {String} The sanitized string - */ -function sanitizeString(str) { - return _.chain(str).deburr().toLower().value().replaceAll(CONST.REGEX.NON_ALPHABETIC_AND_NON_LATIN_CHARS, ''); -} - -export default {sanitizeString}; diff --git a/src/libs/StringUtils.ts b/src/libs/StringUtils.ts new file mode 100644 index 000000000000..8ef23bb0751b --- /dev/null +++ b/src/libs/StringUtils.ts @@ -0,0 +1,13 @@ +import _ from 'lodash'; +import CONST from '../CONST'; + +/** + * Removes diacritical marks and non-alphabetic and non-latin characters from a string. + * @param str - The input string to be sanitized. + * @returns The sanitized string + */ +function sanitizeString(str: string): string { + return _.deburr(str).toLowerCase().replaceAll(CONST.REGEX.NON_ALPHABETIC_AND_NON_LATIN_CHARS, ''); +} + +export default {sanitizeString}; diff --git a/src/libs/Timers.js b/src/libs/Timers.ts similarity index 73% rename from src/libs/Timers.js rename to src/libs/Timers.ts index 49bc6a7350b8..21ee2a8c2914 100644 --- a/src/libs/Timers.js +++ b/src/libs/Timers.ts @@ -1,14 +1,9 @@ -import _ from 'underscore'; - -const timers = []; +const timers: NodeJS.Timer[] = []; /** * Register a timer so it can be cleaned up later. - * - * @param {Number} timerID - * @returns {Number} */ -function register(timerID) { +function register(timerID: NodeJS.Timer): NodeJS.Timer { timers.push(timerID); return timerID; } @@ -16,8 +11,8 @@ function register(timerID) { /** * Clears all timers that we have registered. Use for long running tasks that may begin once logged out. */ -function clearAll() { - _.each(timers, (timer) => { +function clearAll(): void { + timers.forEach((timer) => { // We don't know whether it's a setTimeout or a setInterval, but it doesn't really matter. If the id doesn't // exist nothing bad happens. clearTimeout(timer); diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 16deefef3a00..4ca8b48d284e 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -33,6 +33,7 @@ Onyx.connect({ * @param {Object} [receipt] * @param {String} [filename] * @param {String} [existingTransactionID] When creating a distance request, an empty transaction has already been created with a transactionID. In that case, the transaction here needs to have it's transactionID match what was already generated. + * @param {String} [category] * @returns {Object} */ function buildOptimisticTransaction( @@ -47,6 +48,7 @@ function buildOptimisticTransaction( receipt = {}, filename = '', existingTransactionID = null, + category = '', ) { // transactionIDs are random, positive, 64-bit numeric strings. // Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID) @@ -74,6 +76,7 @@ function buildOptimisticTransaction( pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, receipt, filename, + category, }; } @@ -228,6 +231,16 @@ function getMerchant(transaction) { return lodashGet(transaction, 'modifiedMerchant', null) || lodashGet(transaction, 'merchant', ''); } +/** + * Return the category from the transaction. This "category" field has no "modified" complement. + * + * @param {Object} transaction + * @return {String} + */ +function getCategory(transaction) { + return lodashGet(transaction, 'category', ''); +} + /** * Return the created field from the transaction, return the modifiedCreated if present. * @@ -303,6 +316,15 @@ function waypointHasValidAddress(waypoint) { return true; } +/** + * Converts the key of a waypoint to its index + * @param {String} key + * @returns {Number} waypoint index + */ +function getWaypointIndex(key) { + return Number(key.replace('waypoint', '')); +} + /** * Filters the waypoints which are valid and returns those * @param {Object} waypoints @@ -310,7 +332,8 @@ function waypointHasValidAddress(waypoint) { * @returns {Object} validated waypoints */ function getValidWaypoints(waypoints, reArrangeIndexes = false) { - const waypointValues = _.values(waypoints); + const sortedIndexes = _.map(_.keys(waypoints), (key) => getWaypointIndex(key)).sort(); + const waypointValues = _.map(sortedIndexes, (index) => waypoints[`waypoint${index}`]); // Ensure the number of waypoints is between 2 and 25 if (waypointValues.length < 2 || waypointValues.length > 25) { return {}; @@ -340,7 +363,6 @@ function getValidWaypoints(waypoints, reArrangeIndexes = false) { }, {}, ); - return validWaypoints; } @@ -353,6 +375,7 @@ export { getCurrency, getMerchant, getCreated, + getCategory, getLinkedTransaction, getAllReportTransactions, hasReceipt, @@ -360,4 +383,5 @@ export { getValidWaypoints, isDistanceRequest, hasMissingSmartscanFields, + getWaypointIndex, }; diff --git a/src/libs/Trie/TrieNode.js b/src/libs/Trie/TrieNode.js deleted file mode 100644 index 27597f861620..000000000000 --- a/src/libs/Trie/TrieNode.js +++ /dev/null @@ -1,9 +0,0 @@ -class TrieNode { - constructor() { - this.children = {}; - this.isEndOfWord = false; - this.metaData = {}; - } -} - -export default TrieNode; diff --git a/src/libs/Trie/TrieNode.ts b/src/libs/Trie/TrieNode.ts new file mode 100644 index 000000000000..645ce6747cbb --- /dev/null +++ b/src/libs/Trie/TrieNode.ts @@ -0,0 +1,19 @@ +type MetaData = Record; + +class TrieNode { + children: Record>; + + metaData: Partial; + + isEndOfWord: boolean; + + constructor() { + this.children = {}; + this.metaData = {}; + this.isEndOfWord = false; + } +} + +export default TrieNode; + +export type {MetaData}; diff --git a/src/libs/Trie/index.js b/src/libs/Trie/index.ts similarity index 62% rename from src/libs/Trie/index.js rename to src/libs/Trie/index.ts index 085f62ab4ef5..c3c5aa4bbf3f 100644 --- a/src/libs/Trie/index.js +++ b/src/libs/Trie/index.ts @@ -1,19 +1,23 @@ -import _ from 'underscore'; -import TrieNode from './TrieNode'; +import TrieNode, {MetaData} from './TrieNode'; + +type Word = { + name: string; + metaData: Partial; +}; + +class Trie { + root: TrieNode; -class Trie { constructor() { this.root = new TrieNode(); } /** * Add a word to the Trie - * @param {String} word - * @param {Object} [metaData] - attach additional data to the word - * @param {TrieNode} [node] - * @param {Boolean} [allowEmptyWords] - empty word doesn't have any char, you shouldn't pass a true value for it because we are disallowing adding an empty word + * @param [metaData] - attach additional data to the word + * @param [allowEmptyWords] - empty word doesn't have any char, you shouldn't pass a true value for it because we are disallowing adding an empty word */ - add(word, metaData = {}, node = this.root, allowEmptyWords = false) { + add(word: string, metaData: Partial = {}, node = this.root, allowEmptyWords = false) { const newWord = word.toLowerCase(); const newNode = node; if (newWord.length === 0 && !allowEmptyWords) { @@ -33,10 +37,9 @@ class Trie { /** * Search for a word in the Trie. - * @param {String} word - * @returns {Object|null} – the node for the word if it's found, or null if it's not found + * @returns - the node for the word if it's found, or null if it's not found */ - search(word) { + search(word: string): TrieNode | null { let newWord = word.toLowerCase(); let node = this.root; while (newWord.length > 1) { @@ -52,10 +55,8 @@ class Trie { /** * Update a word data in the Trie. - * @param {String} word - * @param {Object} metaData */ - update(word, metaData) { + update(word: string, metaData: TMetaData) { let newWord = word.toLowerCase(); let node = this.root; while (newWord.length > 1) { @@ -70,33 +71,26 @@ class Trie { /** * Find all leaf nodes starting with a substring. - * @param {String} substr - * @param {Number} [limit] - matching words limit - * @returns {Array} + * @param [limit] - matching words limit */ - getAllMatchingWords(substr, limit = 5) { + getAllMatchingWords(substr: string, limit = 5): Array> { const newSubstr = substr.toLowerCase(); let node = this.root; let prefix = ''; - for (let i = 0; i < newSubstr.length; i++) { - prefix += newSubstr[i]; - if (!node.children[newSubstr[i]]) { + for (const char of newSubstr) { + prefix += char; + if (!node.children[char]) { return []; } - node = node.children[newSubstr[i]]; + node = node.children[char]; } return this.getChildMatching(node, prefix, limit, []); } /** * Find all leaf nodes that are descendants of a given child node. - * @param {TrieNode} node - * @param {String} prefix - * @param {Number} limit - * @param {Array} [words] - * @returns {Array} */ - getChildMatching(node, prefix, limit, words = []) { + getChildMatching(node: TrieNode, prefix: string, limit: number, words: Array> = []): Array> { const matching = words; if (matching.length >= limit) { return matching; @@ -104,9 +98,9 @@ class Trie { if (node.isEndOfWord) { matching.push({name: prefix, metaData: node.metaData}); } - const children = _.keys(node.children); - for (let i = 0; i < children.length; i++) { - this.getChildMatching(node.children[children[i]], prefix + children[i], limit, matching); + const children = Object.keys(node.children); + for (const child of children) { + this.getChildMatching(node.children[child], prefix + child, limit, matching); } return matching; } diff --git a/src/libs/Url.js b/src/libs/Url.ts similarity index 65% rename from src/libs/Url.js rename to src/libs/Url.ts index eb96b697a8fc..a21f007e8468 100644 --- a/src/libs/Url.js +++ b/src/libs/Url.ts @@ -1,10 +1,9 @@ import 'react-native-url-polyfill/auto'; + /** * Add / to the end of any URL if not present - * @param {String} url - * @returns {String} */ -function addTrailingForwardSlash(url) { +function addTrailingForwardSlash(url: string): string { if (!url.endsWith('/')) { return `${url}/`; } @@ -13,10 +12,8 @@ function addTrailingForwardSlash(url) { /** * Get path from URL string - * @param {String} url - * @returns {String} */ -function getPathFromURL(url) { +function getPathFromURL(url: string): string { try { const parsedUrl = new URL(url); const path = parsedUrl.pathname + parsedUrl.search + parsedUrl.hash; @@ -29,12 +26,9 @@ function getPathFromURL(url) { /** * Determine if two urls have the same origin - * @param {String} url1 - * @param {String} url2 - * @returns {Boolean} */ -function hasSameExpensifyOrigin(url1, url2) { - const removeW3 = (host) => host.replace(/^www\./i, ''); +function hasSameExpensifyOrigin(url1: string, url2: string): boolean { + const removeW3 = (host: string) => host.replace(/^www\./i, ''); try { const parsedUrl1 = new URL(url1); const parsedUrl2 = new URL(url2); @@ -47,9 +41,4 @@ function hasSameExpensifyOrigin(url1, url2) { } } -export { - // eslint-disable-next-line import/prefer-default-export - addTrailingForwardSlash, - hasSameExpensifyOrigin, - getPathFromURL, -}; +export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL}; diff --git a/src/libs/UserUtils.js b/src/libs/UserUtils.js index 918c2c9bbdc6..2d5930b0dfd8 100644 --- a/src/libs/UserUtils.js +++ b/src/libs/UserUtils.js @@ -106,9 +106,8 @@ function getDefaultAvatarURL(accountID = '', isNewDot = false) { return CONST.CONCIERGE_ICON_URL; } - // The default avatar for a user is based on a simple hash of their accountID. // Note that Avatar count starts at 1 which is why 1 has to be added to the result (or else 0 would result in a broken avatar link) - const accountIDHashBucket = hashText(String(accountID), isNewDot ? CONST.DEFAULT_AVATAR_COUNT : CONST.OLD_DEFAULT_AVATAR_COUNT) + 1; + const accountIDHashBucket = (Number(accountID) % (isNewDot ? CONST.DEFAULT_AVATAR_COUNT : CONST.OLD_DEFAULT_AVATAR_COUNT)) + 1; const avatarPrefix = isNewDot ? `default-avatar` : `avatar`; return `${CONST.CLOUDFRONT_URL}/images/avatars/${avatarPrefix}_${accountIDHashBucket}.png`; diff --git a/src/libs/VisualViewport/index.native.js b/src/libs/VisualViewport/index.native.ts similarity index 50% rename from src/libs/VisualViewport/index.native.js rename to src/libs/VisualViewport/index.native.ts index c228119b064c..a50b080d9aab 100644 --- a/src/libs/VisualViewport/index.native.js +++ b/src/libs/VisualViewport/index.native.ts @@ -1,10 +1,8 @@ +import AddViewportResizeListener from './types'; + /** * Visual Viewport is not available on native, so return an empty function. - * - * @returns {Function} */ -function addViewportResizeListener() { - return () => {}; -} +const addViewportResizeListener: AddViewportResizeListener = () => () => {}; export default addViewportResizeListener; diff --git a/src/libs/VisualViewport/index.js b/src/libs/VisualViewport/index.ts similarity index 55% rename from src/libs/VisualViewport/index.js rename to src/libs/VisualViewport/index.ts index cc6be038209c..e24d42f272a4 100644 --- a/src/libs/VisualViewport/index.js +++ b/src/libs/VisualViewport/index.ts @@ -1,16 +1,15 @@ +import AddViewportResizeListener from './types'; + /** * Add a visual viewport resize listener if available. Return a function to remove the listener. - * - * @param {Function} onViewportResize - * @returns {Function} */ -function addViewportResizeListener(onViewportResize) { +const addViewportResizeListener: AddViewportResizeListener = (onViewportResize) => { if (!window.visualViewport) { return () => {}; } window.visualViewport.addEventListener('resize', onViewportResize); - return () => window.visualViewport.removeEventListener('resize', onViewportResize); -} + return () => window.visualViewport?.removeEventListener('resize', onViewportResize); +}; export default addViewportResizeListener; diff --git a/src/libs/VisualViewport/types.ts b/src/libs/VisualViewport/types.ts new file mode 100644 index 000000000000..da8360d72a35 --- /dev/null +++ b/src/libs/VisualViewport/types.ts @@ -0,0 +1,3 @@ +type AddViewportResizeListener = (onViewportResize: (e: Event) => void) => () => void; + +export default AddViewportResizeListener; diff --git a/src/libs/actions/ActiveClients.js b/src/libs/actions/ActiveClients.ts similarity index 69% rename from src/libs/actions/ActiveClients.js rename to src/libs/actions/ActiveClients.ts index 744944cfef1c..45fcff402f49 100644 --- a/src/libs/actions/ActiveClients.js +++ b/src/libs/actions/ActiveClients.ts @@ -1,11 +1,7 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -/** - * @param {Array} activeClients - * @return {Promise} - */ -function setActiveClients(activeClients) { +function setActiveClients(activeClients: string[]): Promise { return Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients); } diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 90c2a9ec4f16..fffe43b88ee9 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -1,4 +1,3 @@ -import moment from 'moment-timezone'; import {AppState} from 'react-native'; import Onyx from 'react-native-onyx'; import lodashGet from 'lodash/get'; @@ -385,7 +384,7 @@ function openProfile(personalDetails) { if (lodashGet(oldTimezoneData, 'automatic', true)) { newTimezoneData = { automatic: true, - selected: moment.tz.guess(true), + selected: Intl.DateTimeFormat().resolvedOptions().timeZone, }; } diff --git a/src/libs/actions/Composer.js b/src/libs/actions/Composer.ts similarity index 69% rename from src/libs/actions/Composer.js rename to src/libs/actions/Composer.ts index 9a75e3662cd8..d3f9ef9814a5 100644 --- a/src/libs/actions/Composer.js +++ b/src/libs/actions/Composer.ts @@ -1,10 +1,7 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -/** - * @param {Boolean} shouldShowComposeInput - */ -function setShouldShowComposeInput(shouldShowComposeInput) { +function setShouldShowComposeInput(shouldShowComposeInput: boolean) { Onyx.set(ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT, shouldShowComposeInput); } diff --git a/src/libs/actions/CurrentDate.js b/src/libs/actions/CurrentDate.ts similarity index 74% rename from src/libs/actions/CurrentDate.js rename to src/libs/actions/CurrentDate.ts index 078b35a760cb..b19a3430e96f 100644 --- a/src/libs/actions/CurrentDate.js +++ b/src/libs/actions/CurrentDate.ts @@ -1,10 +1,7 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -/** - * @param {String} currentDate - */ -function setCurrentDate(currentDate) { +function setCurrentDate(currentDate: string) { Onyx.set(ONYXKEYS.CURRENT_DATE, currentDate); } diff --git a/src/libs/actions/DemoActions.js b/src/libs/actions/DemoActions.js deleted file mode 100644 index 4ba9f6ee33a0..000000000000 --- a/src/libs/actions/DemoActions.js +++ /dev/null @@ -1,108 +0,0 @@ -import Onyx from 'react-native-onyx'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; -import CONST from '../../CONST'; -import * as API from '../API'; -import * as ReportUtils from '../ReportUtils'; -import Navigation from '../Navigation/Navigation'; -import ROUTES from '../../ROUTES'; -import ONYXKEYS from '../../ONYXKEYS'; -import * as Localize from '../Localize'; - -/** - * @param {String} workspaceOwnerEmail email of the workspace owner - * @param {String} apiCommand - */ -function createDemoWorkspaceAndNavigate(workspaceOwnerEmail, apiCommand) { - // Try to navigate to existing demo workspace expense chat if it exists in Onyx - const demoWorkspaceChatReportID = ReportUtils.getPolicyExpenseChatReportIDByOwner(workspaceOwnerEmail); - if (demoWorkspaceChatReportID) { - // We must call goBack() to remove the demo route from nav history - Navigation.goBack(); - Navigation.navigate(ROUTES.getReportRoute(demoWorkspaceChatReportID)); - return; - } - - // We use makeRequestWithSideEffects here because we need to get the workspace chat report ID to navigate to it after it's created - // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects(apiCommand).then((response) => { - // Get report updates from Onyx response data - const reportUpdate = _.find(response.onyxData, ({key}) => key === ONYXKEYS.COLLECTION.REPORT); - if (!reportUpdate) { - // If there's no related onyx data, navigate the user home so they're not stuck. - Navigation.goBack(); - Navigation.navigate(ROUTES.HOME); - return; - } - - // Get the policy expense chat update - const policyExpenseChatReport = _.find(reportUpdate.value, ({chatType}) => chatType === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT); - if (!policyExpenseChatReport) { - // If there's no related onyx data, navigate the user home so they're not stuck. - Navigation.goBack(); - Navigation.navigate(ROUTES.HOME); - return; - } - - // Navigate to the new policy expense chat report - // Note: We must call goBack() to remove the demo route from history - Navigation.goBack(); - Navigation.navigate(ROUTES.getReportRoute(policyExpenseChatReport.reportID)); - }); -} - -function runSbeDemo() { - createDemoWorkspaceAndNavigate(CONST.EMAIL.SBE, 'CreateSbeDemoWorkspace'); -} - -function runSaastrDemo() { - createDemoWorkspaceAndNavigate(CONST.EMAIL.SAASTR, 'CreateSaastrDemoWorkspace'); -} - -/** - * Runs code for specific demos, based on the provided URL - * - * @param {String} url - URL user is navigating to via deep link (or regular link in web) - */ -function runDemoByURL(url = '') { - const cleanUrl = (url || '').toLowerCase(); - - if (cleanUrl.endsWith(ROUTES.SAASTR)) { - Onyx.set(ONYXKEYS.DEMO_INFO, { - saastr: { - isBeginningDemo: true, - }, - }); - } else if (cleanUrl.endsWith(ROUTES.SBE)) { - Onyx.set(ONYXKEYS.DEMO_INFO, { - sbe: { - isBeginningDemo: true, - }, - }); - } else { - // No demo is being run, so clear out demo info - Onyx.set(ONYXKEYS.DEMO_INFO, null); - } -} - -/** - * @param {Object} demoInfo - * @returns {Object} - */ -function getCustomTextForDemo(demoInfo = {}) { - if (lodashGet(demoInfo, 'saastr.isBeginningDemo')) { - return { - customHeadline: Localize.translateLocal('demos.saastr.signInWelcome'), - customHeroBody: Localize.translateLocal('demos.saastr.heroBody'), - }; - } - if (lodashGet(demoInfo, 'sbe.isBeginningDemo')) { - return { - customHeadline: Localize.translateLocal('demos.sbe.signInWelcome'), - customHeroBody: Localize.translateLocal('demos.sbe.heroBody'), - }; - } - return {}; -} - -export {runSaastrDemo, runSbeDemo, runDemoByURL, getCustomTextForDemo}; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index bc7adf47bd8c..8f18119203be 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -44,6 +44,13 @@ Onyx.connect({ }, }); +let allRecentlyUsedCategories = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES, + waitForCollectionCallback: true, + callback: (val) => (allRecentlyUsedCategories = val), +}); + let userAccountID = ''; let currentUserEmail = ''; Onyx.connect({ @@ -83,6 +90,7 @@ function resetMoneyRequestInfo(id = '') { comment: '', participants: [], merchant: CONST.TRANSACTION.DEFAULT_MERCHANT, + category: '', created, receiptPath: '', receiptSource: '', @@ -99,6 +107,7 @@ function buildOnyxDataForMoneyRequest( iouAction, optimisticPersonalDetailListAction, reportPreviewAction, + optimisticRecentlyUsedCategories, isNewChatReport, isNewIOUReport, ) { @@ -148,6 +157,14 @@ function buildOnyxDataForMoneyRequest( }, ]; + if (!_.isEmpty(optimisticRecentlyUsedCategories)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`, + value: optimisticRecentlyUsedCategories, + }); + } + if (!_.isEmpty(optimisticPersonalDetailListAction)) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -319,6 +336,8 @@ function buildOnyxDataForMoneyRequest( * @param {Number} [payeeAccountID] * @param {String} [payeeEmail] * @param {Object} [receipt] + * @param {String} [existingTransactionID] + * @param {String} [category] * @returns {Object} data * @returns {String} data.payerEmail * @returns {Object} data.iouReport @@ -332,7 +351,6 @@ function buildOnyxDataForMoneyRequest( * @returns {Object} data.onyxData.optimisticData * @returns {Object} data.onyxData.successData * @returns {Object} data.onyxData.failureData - * @param {String} [existingTransactionID] */ function getMoneyRequestInformation( report, @@ -345,7 +363,8 @@ function getMoneyRequestInformation( payeeAccountID = userAccountID, payeeEmail = currentUserEmail, receipt = undefined, - existingTransactionID = null, + existingTransactionID = undefined, + category = undefined, ) { const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login); const payerAccountID = Number(participant.accountID); @@ -410,8 +429,17 @@ function getMoneyRequestInformation( receiptObject, filename, existingTransactionID, + category, ); + const uniquePolicyRecentlyUsedCategories = allRecentlyUsedCategories + ? _.filter( + allRecentlyUsedCategories[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`], + (recentlyUsedPolicyCategory) => recentlyUsedPolicyCategory !== category, + ) + : []; + const optimisticPolicyRecentlyUsedCategories = [category, ...uniquePolicyRecentlyUsedCategories]; + // If there is an existing transaction (which is the case for distance requests), then the data from the existing transaction // needs to be manually merged into the optimistic transaction. This is because buildOnyxDataForMoneyRequest() uses `Onyx.set()` for the transaction // data. This is a big can of worms to change it to `Onyx.merge()` as explored in https://expensify.slack.com/archives/C05DWUDHVK7/p1692139468252109. @@ -452,6 +480,10 @@ function getMoneyRequestInformation( reportPreviewAction = ReportUtils.updateReportPreview(iouReport, reportPreviewAction, comment, optimisticTransaction); } else { reportPreviewAction = ReportUtils.buildOptimisticReportPreview(chatReport, iouReport, comment, optimisticTransaction); + + // Generated ReportPreview action is a parent report action of the iou report. + // We are setting the iou report's parentReportActionID to display subtitle correctly in IOU page when offline. + iouReport.parentReportActionID = reportPreviewAction.reportActionID; } // Add optimistic personal details for participant @@ -476,6 +508,7 @@ function getMoneyRequestInformation( iouAction, optimisticPersonalDetailListAction, reportPreviewAction, + optimisticPolicyRecentlyUsedCategories, isNewChatReport, isNewIOUReport, ); @@ -505,11 +538,12 @@ function getMoneyRequestInformation( * @param {String} comment * @param {String} created * @param {String} [transactionID] + * @param {String} [category] * @param {Number} amount * @param {String} currency * @param {String} merchant */ -function createDistanceRequest(report, participant, comment, created, transactionID, amount, currency, merchant) { +function createDistanceRequest(report, participant, comment, created, transactionID, category, amount, currency, merchant) { const optimisticReceipt = { source: ReceiptGeneric, state: CONST.IOU.RECEIPT_STATE.OPEN, @@ -526,6 +560,7 @@ function createDistanceRequest(report, participant, comment, created, transactio null, optimisticReceipt, transactionID, + category, ); API.write( 'CreateDistanceRequest', @@ -540,6 +575,7 @@ function createDistanceRequest(report, participant, comment, created, transactio reportPreviewReportActionID: reportPreviewAction.reportActionID, waypoints: JSON.stringify(TransactionUtils.getValidWaypoints(transaction.comment.waypoints, true)), created, + category, }, onyxData, ); @@ -560,10 +596,14 @@ function createDistanceRequest(report, participant, comment, created, transactio * @param {Object} participant * @param {String} comment * @param {Object} [receipt] + * @param {String} [category] */ -function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) { +function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined, category = undefined) { + // If the report is iou or expense report, we should get the linked chat report to be passed to the getMoneyRequestInformation function + const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); + const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report; const {payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} = getMoneyRequestInformation( - report, + currentChatReport, participant, comment, amount, @@ -573,6 +613,8 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p payeeAccountID, payeeEmail, receipt, + undefined, + category, ); API.write( @@ -592,11 +634,12 @@ function requestMoney(report, amount, currency, created, merchant, payeeEmail, p createdIOUReportActionID, reportPreviewReportActionID: reportPreviewAction.reportActionID, receipt, + category, }, onyxData, ); resetMoneyRequestInfo(); - Navigation.dismissModal(chatReport.reportID); + Navigation.dismissModal(isMoneyRequestReport ? report.reportID : chatReport.reportID); Report.notifyNewAction(chatReport.reportID, payeeAccountID); } @@ -874,6 +917,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco oneOnOneIOUAction, oneOnOnePersonalDetailListAction, oneOnOneReportPreviewAction, + [], isNewOneOnOneChatReport, shouldCreateNewOneOnOneIOUReport, ); @@ -989,12 +1033,50 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`]; + const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`]; const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); // STEP 2: Build new modified expense report action. const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport); const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport); + // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct + // Should only update if the transaction matches the currency of the report, else we wait for the update + // from the server with the currency conversion + let updatedMoneyRequestReport = {...iouReport}; + const updatedChatReport = {...chatReport}; + if (updatedTransaction.currency === iouReport.currency && updatedTransaction.modifiedAmount) { + const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true); + if (ReportUtils.isExpenseReport(iouReport)) { + updatedMoneyRequestReport.total += diff; + } else { + updatedMoneyRequestReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID, diff, TransactionUtils.getCurrency(transaction), false); + } + + updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction.currency); + + // Update the last message of the IOU report + const lastMessage = ReportUtils.getIOUReportActionMessage( + iouReport.reportID, + CONST.IOU.REPORT_ACTION_TYPE.CREATE, + updatedMoneyRequestReport.total, + '', + updatedTransaction.currency, + '', + false, + ); + updatedMoneyRequestReport.lastMessageText = lastMessage[0].text; + updatedMoneyRequestReport.lastMessageHtml = lastMessage[0].html; + + // Update the last message of the chat report + const messageText = Localize.translateLocal('iou.payerOwesAmount', { + payer: updatedMoneyRequestReport.managerEmail, + amount: CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedMoneyRequestReport.currency), + }); + updatedChatReport.lastMessageText = messageText; + updatedChatReport.lastMessageHtml = messageText; + } + // STEP 4: Compose the optimistic data const optimisticData = [ { @@ -1009,6 +1091,16 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, value: updatedTransaction, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + value: updatedMoneyRequestReport, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`, + value: updatedChatReport, + }, ]; const successData = [ @@ -1032,6 +1124,11 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC }, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + value: {pendingAction: null}, + }, ]; const failureData = [ @@ -1049,13 +1146,18 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.report}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, value: iouReport, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`, + value: chatReport, + }, ]; // STEP 6: Call the API endpoint - const {created, amount, currency, comment, merchant} = ReportUtils.getTransactionDetails(updatedTransaction); + const {created, amount, currency, comment, merchant, category} = ReportUtils.getTransactionDetails(updatedTransaction); API.write( 'EditMoneyRequest', { @@ -1066,6 +1168,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC currency, comment, merchant, + category, }, {optimisticData, successData, failureData}, ); @@ -1831,6 +1934,17 @@ function setMoneyRequestMerchant(merchant) { Onyx.merge(ONYXKEYS.IOU, {merchant: merchant.trim()}); } +/** + * @param {String} category + */ +function setMoneyRequestCategory(category) { + Onyx.merge(ONYXKEYS.IOU, {category}); +} + +function resetMoneyRequestCategory() { + Onyx.merge(ONYXKEYS.IOU, {category: ''}); +} + /** * @param {Object[]} participants */ @@ -1872,12 +1986,14 @@ function navigateToNextPage(iou, iouType, reportID, report) { // If a request is initiated on a report, skip the participants selection step and navigate to the confirmation page. if (report.reportID) { + // If the report is iou or expense report, we should get the chat report to set participant for request money + const chatReport = ReportUtils.isMoneyRequestReport(report) ? ReportUtils.getReport(report.chatReportID) : report; // Reinitialize the participants when the money request ID in Onyx does not match the ID from params if (_.isEmpty(iou.participants) || shouldReset) { const currentUserAccountID = currentUserPersonalDetails.accountID; - const participants = ReportUtils.isPolicyExpenseChat(report) - ? [{reportID: report.reportID, isPolicyExpenseChat: true, selected: true}] - : _.chain(report.participantAccountIDs) + const participants = ReportUtils.isPolicyExpenseChat(chatReport) + ? [{reportID: chatReport.reportID, isPolicyExpenseChat: true, selected: true}] + : _.chain(chatReport.participantAccountIDs) .filter((accountID) => currentUserAccountID !== accountID) .map((accountID) => ({accountID, selected: true})) .value(); @@ -1909,6 +2025,8 @@ export { setMoneyRequestCurrency, setMoneyRequestDescription, setMoneyRequestMerchant, + setMoneyRequestCategory, + resetMoneyRequestCategory, setMoneyRequestParticipants, setMoneyRequestReceipt, createEmptyTransaction, diff --git a/src/libs/actions/Modal.js b/src/libs/actions/Modal.ts similarity index 74% rename from src/libs/actions/Modal.js rename to src/libs/actions/Modal.ts index ea3bfc351593..ff09731f59a7 100644 --- a/src/libs/actions/Modal.js +++ b/src/libs/actions/Modal.ts @@ -1,25 +1,20 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -let closeModal; -let onModalClose; +let closeModal: (isNavigating: boolean) => void; +let onModalClose: null | (() => void); /** * Allows other parts of the app to call modal close function - * - * @param {Function} [onClose] */ -function setCloseModal(onClose) { +function setCloseModal(onClose: () => void) { closeModal = onClose; } /** * Close modal in other parts of the app - * - * @param {Function} [onModalCloseCallback] - * @param {Boolean} isNavigating */ -function close(onModalCloseCallback, isNavigating = true) { +function close(onModalCloseCallback: () => void, isNavigating = true) { if (!closeModal) { // If modal is already closed, no need to wait for modal close. So immediately call callback. if (onModalCloseCallback) { @@ -42,20 +37,16 @@ function onModalDidClose() { /** * Allows other parts of the app to know when a modal has been opened or closed - * - * @param {Boolean} isVisible */ -function setModalVisibility(isVisible) { +function setModalVisibility(isVisible: boolean) { Onyx.merge(ONYXKEYS.MODAL, {isVisible}); } /** * Allows other parts of app to know that an alert modal is about to open. * This will trigger as soon as a modal is opened but not yet visible while animation is running. - * - * @param {Boolean} isVisible */ -function willAlertModalBecomeVisible(isVisible) { +function willAlertModalBecomeVisible(isVisible: boolean) { Onyx.merge(ONYXKEYS.MODAL, {willAlertModalBecomeVisible: isVisible}); } diff --git a/src/libs/actions/Network.js b/src/libs/actions/Network.ts similarity index 58% rename from src/libs/actions/Network.js rename to src/libs/actions/Network.ts index 892ba92f6973..212e44f6782d 100644 --- a/src/libs/actions/Network.js +++ b/src/libs/actions/Network.ts @@ -1,26 +1,18 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; -/** - * @param {Boolean} isOffline - */ -function setIsOffline(isOffline) { +function setIsOffline(isOffline: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {isOffline}); } -/** - * - * @param {Boolean} shouldForceOffline - */ -function setShouldForceOffline(shouldForceOffline) { +function setShouldForceOffline(shouldForceOffline: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); } /** * Test tool that will fail all network requests when enabled - * @param {Boolean} shouldFailAllRequests */ -function setShouldFailAllRequests(shouldFailAllRequests) { +function setShouldFailAllRequests(shouldFailAllRequests: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {shouldFailAllRequests}); } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 85552fa14a56..2961784d5825 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -25,9 +25,9 @@ import * as ErrorUtils from '../ErrorUtils'; import * as UserUtils from '../UserUtils'; import * as Welcome from './Welcome'; import * as PersonalDetailsUtils from '../PersonalDetailsUtils'; -import SidebarUtils from '../SidebarUtils'; import * as OptionsListUtils from '../OptionsListUtils'; import * as Environment from '../Environment/Environment'; +import * as Session from './Session'; let currentUserAccountID; Onyx.connect({ @@ -1759,13 +1759,16 @@ function openReportFromDeepLink(url, isAuthenticated) { // Navigate to the report after sign-in/sign-up. InteractionManager.runAfterInteractions(() => { - SidebarUtils.isSidebarLoadedReady().then(() => { + Session.waitForUserSignIn().then(() => { if (reportID) { Navigation.navigate(ROUTES.getReportRoute(reportID), CONST.NAVIGATION.TYPE.UP); + return; } if (route === ROUTES.CONCIERGE) { navigateToConciergeChat(); + return; } + Navigation.navigate(route, CONST.NAVIGATION.TYPE.PUSH); }); }); } diff --git a/src/libs/actions/ReportActions.js b/src/libs/actions/ReportActions.js index 55d81cb6eb14..d270876840ac 100644 --- a/src/libs/actions/ReportActions.js +++ b/src/libs/actions/ReportActions.js @@ -2,20 +2,23 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; import CONST from '../../CONST'; import * as ReportActionUtils from '../ReportActionsUtils'; +import * as ReportUtils from '../ReportUtils'; /** * @param {String} reportID * @param {Object} reportAction */ function clearReportActionErrors(reportID, reportAction) { + const originalReportID = ReportUtils.getOriginalReportID(reportID, reportAction); + if (reportAction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { // Delete the optimistic action - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`, { [reportAction.reportActionID]: null, }); // If there's a linked transaction, delete that too - const linkedTransactionID = ReportActionUtils.getLinkedTransactionID(reportID, reportAction.reportActionID); + const linkedTransactionID = ReportActionUtils.getLinkedTransactionID(originalReportID, reportAction.reportActionID); if (linkedTransactionID) { Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${linkedTransactionID}`, null); } @@ -23,7 +26,7 @@ function clearReportActionErrors(reportID, reportAction) { return; } - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`, { [reportAction.reportActionID]: { errors: null, }, diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index aa5ff229267f..8a8aabf6e8f4 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -20,13 +20,23 @@ import * as Device from '../Device'; import ROUTES from '../../../ROUTES'; import * as ErrorUtils from '../../ErrorUtils'; import * as ReportUtils from '../../ReportUtils'; -import * as Report from '../Report'; import {hideContextMenu} from '../../../pages/home/report/ContextMenu/ReportActionContextMenu'; -let authTokenType = ''; +let sessionAuthTokenType = ''; +let sessionAuthToken = null; +let authPromiseResolver = null; + Onyx.connect({ key: ONYXKEYS.SESSION, - callback: (session) => (authTokenType = lodashGet(session, 'authTokenType')), + callback: (session) => { + sessionAuthTokenType = lodashGet(session, 'authTokenType'); + sessionAuthToken = lodashGet(session, 'authToken'); + + if (sessionAuthToken && authPromiseResolver) { + authPromiseResolver(true); + authPromiseResolver = null; + } + }, }); let credentials = {}; @@ -61,7 +71,7 @@ function signOut() { * @return {boolean} */ function isAnonymousUser() { - return authTokenType === 'anonymousAccount'; + return sessionAuthTokenType === 'anonymousAccount'; } function signOutAndRedirectToSignIn() { @@ -75,7 +85,7 @@ function signOutAndRedirectToSignIn() { Linking.getInitialURL().then((url) => { const reportID = ReportUtils.getReportIDFromLink(url); if (reportID) { - Report.setLastOpenedPublicRoom(reportID); + Onyx.merge(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, reportID); } }); } @@ -749,6 +759,29 @@ function validateTwoFactorAuth(twoFactorAuthCode) { API.write('TwoFactorAuth_Validate', {twoFactorAuthCode}, {optimisticData, successData, failureData}); } +/** + * Waits for a user to sign in. + * + * If the user is already signed in (`authToken` is truthy), the promise resolves immediately. + * Otherwise, the promise will resolve when the `authToken` in `ONYXKEYS.SESSION` becomes truthy via the Onyx callback. + * The promise will not reject on failed login attempt. + * + * @returns {Promise} A promise that resolves to `true` once the user is signed in. + * @example + * waitForUserSignIn().then(() => { + * console.log('User is signed in!'); + * }); + */ +function waitForUserSignIn() { + return new Promise((resolve) => { + if (sessionAuthToken) { + resolve(true); + } else { + authPromiseResolver = resolve; + } + }); +} + export { beginSignIn, beginAppleSignIn, @@ -776,4 +809,5 @@ export { isAnonymousUser, toggleTwoFactorAuth, validateTwoFactorAuth, + waitForUserSignIn, }; diff --git a/src/libs/actions/Tab.js b/src/libs/actions/Tab.ts similarity index 54% rename from src/libs/actions/Tab.js rename to src/libs/actions/Tab.ts index 0af197361b70..7acd978d6b1a 100644 --- a/src/libs/actions/Tab.js +++ b/src/libs/actions/Tab.ts @@ -3,12 +3,9 @@ import ONYXKEYS from '../../ONYXKEYS'; /** * Sets the selected tab for a given tab ID - * - * @param {String} id - * @param {String} index */ -function setSelectedTab(id, index) { - Onyx.merge(`${ONYXKEYS.SELECTED_TAB}_${id}`, index); +function setSelectedTab(id: string, index: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`, index); } export default { diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index d66cc243acf4..2d599053ea51 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -187,6 +187,8 @@ function createTaskAndNavigate(parentReportID, title, description, assigneeEmail value: {[optimisticAddCommentReport.reportAction.reportActionID]: {pendingAction: null}}, }); + clearOutTaskInfo(); + API.write( 'CreateTask', { @@ -270,12 +272,6 @@ function completeTask(taskReport, taskTitle) { }, ]; - // Update optimistic data for parent report action - const optimisticDataForParentReportAction = ReportUtils.getOptimisticDataForParentReportAction(taskReportID, completedTaskReportAction.created, CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - if (!_.isEmpty(optimisticDataForParentReportAction)) { - optimisticData.push(optimisticDataForParentReportAction); - } - // Multiple report actions can link to the same child. Both share destination (task parent) and assignee report link to the same report action. // We need to find and update the other parent report action (in assignee report). More info https://github.com/Expensify/App/issues/23920#issuecomment-1663092717 const assigneeReportAction = ReportUtils.getTaskParentReportActionIDInAssigneeReport(taskReport); @@ -363,12 +359,6 @@ function reopenTask(taskReport, taskTitle) { }, ]; - // Update optimistic data for parent report action - const optimisticDataForParentReportAction = ReportUtils.getOptimisticDataForParentReportAction(taskReportID, reopenedTaskReportAction.created, CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - if (!_.isEmpty(optimisticDataForParentReportAction)) { - optimisticData.push(optimisticDataForParentReportAction); - } - // Multiple report actions can link to the same child. Both share destination (task parent) and assignee report link to the same report action. // We need to find and update the other parent report action (in assignee report). More info https://github.com/Expensify/App/issues/23920#issuecomment-1663092717 const assigneeReportAction = ReportUtils.getTaskParentReportActionIDInAssigneeReport(taskReport); diff --git a/src/libs/actions/TwoFactorAuthActions.js b/src/libs/actions/TwoFactorAuthActions.ts similarity index 85% rename from src/libs/actions/TwoFactorAuthActions.js rename to src/libs/actions/TwoFactorAuthActions.ts index 3bc64b8ada4c..0cec7d3c16c8 100644 --- a/src/libs/actions/TwoFactorAuthActions.js +++ b/src/libs/actions/TwoFactorAuthActions.ts @@ -2,6 +2,7 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; import Navigation from '../Navigation/Navigation'; import ROUTES from '../../ROUTES'; +import {TwoFactorAuthStep} from '../../types/onyx/Account'; /** * Clear 2FA data if the flow is interrupted without finishing @@ -9,8 +10,7 @@ import ROUTES from '../../ROUTES'; function clearTwoFactorAuthData() { Onyx.merge(ONYXKEYS.ACCOUNT, {recoveryCodes: '', twoFactorAuthSecretKey: '', twoFactorAuthStep: '', codesAreCopied: false}); } - -function setTwoFactorAuthStep(twoFactorAuthStep) { +function setTwoFactorAuthStep(twoFactorAuthStep: TwoFactorAuthStep) { Onyx.merge(ONYXKEYS.ACCOUNT, {twoFactorAuthStep}); } diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index ee93c6acb1e5..7482c13268e4 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -19,6 +19,7 @@ import * as ErrorUtils from '../ErrorUtils'; import * as Session from './Session'; import * as PersonalDetails from './PersonalDetails'; import * as OnyxUpdates from './OnyxUpdates'; +import redirectToSignIn from './SignInRedirect'; let currentUserAccountID = ''; let currentEmail = ''; @@ -70,6 +71,8 @@ function closeAccount(message) { ], }, ); + // Run cleanup actions to prevent reconnection callbacks from blocking logging in again + redirectToSignIn(); } /** diff --git a/src/libs/addEncryptedAuthTokenToURL.js b/src/libs/addEncryptedAuthTokenToURL.ts similarity index 58% rename from src/libs/addEncryptedAuthTokenToURL.js rename to src/libs/addEncryptedAuthTokenToURL.ts index 827454fa2aa3..9bdb83c284ce 100644 --- a/src/libs/addEncryptedAuthTokenToURL.js +++ b/src/libs/addEncryptedAuthTokenToURL.ts @@ -1,19 +1,15 @@ -import lodashGet from 'lodash/get'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '../ONYXKEYS'; let encryptedAuthToken = ''; Onyx.connect({ key: ONYXKEYS.SESSION, - callback: (session) => (encryptedAuthToken = lodashGet(session, 'encryptedAuthToken', '')), + callback: (session) => (encryptedAuthToken = session?.encryptedAuthToken ?? ''), }); /** * Add encryptedAuthToken to this attachment URL - * - * @param {String} url - * @returns {String} */ -export default function (url) { +export default function (url: string) { return `${url}?encryptedAuthToken=${encodeURIComponent(encryptedAuthToken)}`; } diff --git a/src/libs/focusTextInputAfterAnimation/index.native.js b/src/libs/focusTextInputAfterAnimation/index.native.ts similarity index 61% rename from src/libs/focusTextInputAfterAnimation/index.native.js rename to src/libs/focusTextInputAfterAnimation/index.native.ts index 8cd44d111642..2ccbfe7368b2 100644 --- a/src/libs/focusTextInputAfterAnimation/index.native.js +++ b/src/libs/focusTextInputAfterAnimation/index.native.ts @@ -1,14 +1,15 @@ +import FocusTextInputAfterAnimation from './types'; + /** * Focus the text input with a slight delay to make sure modals are closed first. * Since in react-native-modal `onModalHide` is called before the modal is actually hidden. * It results in the keyboard being dismissed right away on both iOS and Android. * See this discussion for more details: https://github.com/Expensify/App/issues/18300 * - * @param {Object} inputRef - * @param {Number} animationLength you must use your best guess as to what a good animationLength is. It can't be too short, or the animation won't be finished. It can't be too long or + * @param animationLength you must use your best guess as to what a good animationLength is. It can't be too short, or the animation won't be finished. It can't be too long or * the user will notice that it feels sluggish */ -const focusTextInputAfterAnimation = (inputRef, animationLength = 0) => { +const focusTextInputAfterAnimation: FocusTextInputAfterAnimation = (inputRef, animationLength = 0) => { setTimeout(() => { inputRef.focus(); }, animationLength); diff --git a/src/libs/focusTextInputAfterAnimation/index.js b/src/libs/focusTextInputAfterAnimation/index.ts similarity index 61% rename from src/libs/focusTextInputAfterAnimation/index.js rename to src/libs/focusTextInputAfterAnimation/index.ts index dba6e0fdcddc..1e3211372b41 100644 --- a/src/libs/focusTextInputAfterAnimation/index.js +++ b/src/libs/focusTextInputAfterAnimation/index.ts @@ -1,9 +1,9 @@ +import FocusTextInputAfterAnimation from './types'; + /** * This library is a no-op for all platforms except for Android and iOS and will immediately focus the given input without any delays. - * - * @param {Object} inputRef */ -const focusTextInputAfterAnimation = (inputRef) => { +const focusTextInputAfterAnimation: FocusTextInputAfterAnimation = (inputRef) => { inputRef.focus(); }; diff --git a/src/libs/focusTextInputAfterAnimation/types.ts b/src/libs/focusTextInputAfterAnimation/types.ts new file mode 100644 index 000000000000..905ac7db4b7a --- /dev/null +++ b/src/libs/focusTextInputAfterAnimation/types.ts @@ -0,0 +1,5 @@ +import {TextInput} from 'react-native'; + +type FocusTextInputAfterAnimation = (inputRef: TextInput | HTMLInputElement, animationLength: number) => void; + +export default FocusTextInputAfterAnimation; diff --git a/src/libs/getComponentDisplayName.js b/src/libs/getComponentDisplayName.js deleted file mode 100644 index 4c643bff1bfa..000000000000 --- a/src/libs/getComponentDisplayName.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Returns the display name of a component - * - * @param {object} component - * @returns {string} - */ -export default function getComponentDisplayName(component) { - return component.displayName || component.name || 'Component'; -} diff --git a/src/libs/getComponentDisplayName.ts b/src/libs/getComponentDisplayName.ts new file mode 100644 index 000000000000..fd1bbcaea521 --- /dev/null +++ b/src/libs/getComponentDisplayName.ts @@ -0,0 +1,6 @@ +import {ComponentType} from 'react'; + +/** Returns the display name of a component */ +export default function getComponentDisplayName(component: ComponentType): string { + return component.displayName ?? component.name ?? 'Component'; +} diff --git a/src/libs/getSecureEntryKeyboardType/index.android.js b/src/libs/getSecureEntryKeyboardType/index.android.js deleted file mode 100644 index 03ba8f571fe9..000000000000 --- a/src/libs/getSecureEntryKeyboardType/index.android.js +++ /dev/null @@ -1,11 +0,0 @@ -import CONST from '../../CONST'; - -/** - * Return visible-password keyboard type when secure text is visible on Android, - * otherwise return keyboardType passed as function parameter - * @param {String} keyboardType - * @param {Boolean} secureTextEntry - * @param {Boolean} passwordHidden - * @return {String} - */ -export default (keyboardType, secureTextEntry, passwordHidden) => (secureTextEntry && !passwordHidden ? CONST.KEYBOARD_TYPE.VISIBLE_PASSWORD : keyboardType); diff --git a/src/libs/getSecureEntryKeyboardType/index.android.ts b/src/libs/getSecureEntryKeyboardType/index.android.ts new file mode 100644 index 000000000000..afd808f35b10 --- /dev/null +++ b/src/libs/getSecureEntryKeyboardType/index.android.ts @@ -0,0 +1,11 @@ +import CONST from '../../CONST'; +import GetSecureEntryKeyboardType from './types'; + +/** + * Return visible-password keyboard type when secure text is visible on Android, + * otherwise return keyboardType passed as function parameter + */ +const getSecureEntryKeyboardType: GetSecureEntryKeyboardType = (keyboardType, secureTextEntry, passwordHidden) => + secureTextEntry && !passwordHidden ? CONST.KEYBOARD_TYPE.VISIBLE_PASSWORD : keyboardType; + +export default getSecureEntryKeyboardType; diff --git a/src/libs/getSecureEntryKeyboardType/index.js b/src/libs/getSecureEntryKeyboardType/index.js deleted file mode 100644 index f6e2b9919b10..000000000000 --- a/src/libs/getSecureEntryKeyboardType/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Return keyboardType passed as function parameter on Web/Desktop/iOS - * @param {String} keyboardType - * @return {String} - */ -export default (keyboardType) => keyboardType; diff --git a/src/libs/getSecureEntryKeyboardType/index.ts b/src/libs/getSecureEntryKeyboardType/index.ts new file mode 100644 index 000000000000..030a88e60e84 --- /dev/null +++ b/src/libs/getSecureEntryKeyboardType/index.ts @@ -0,0 +1,8 @@ +import GetSecureEntryKeyboardType from './types'; + +/** + * Return keyboardType passed as function parameter on Web/Desktop/iOS + */ +const getSecureEntryKeyboardType: GetSecureEntryKeyboardType = (keyboardType) => keyboardType; + +export default getSecureEntryKeyboardType; diff --git a/src/libs/getSecureEntryKeyboardType/types.ts b/src/libs/getSecureEntryKeyboardType/types.ts new file mode 100644 index 000000000000..fe79440e3109 --- /dev/null +++ b/src/libs/getSecureEntryKeyboardType/types.ts @@ -0,0 +1,3 @@ +type GetSecureEntryKeyboardType = (keyboardType: string, secureTextEntry: boolean, passwordHidden: boolean) => string; + +export default GetSecureEntryKeyboardType; diff --git a/src/libs/hashCode.js b/src/libs/hashCode.ts similarity index 80% rename from src/libs/hashCode.js rename to src/libs/hashCode.ts index a95d0787a6e3..bb0522c25de0 100644 --- a/src/libs/hashCode.js +++ b/src/libs/hashCode.ts @@ -2,11 +2,11 @@ /** * Simple string hashing function obtained from: https://stackoverflow.com/a/8831937/16434681 * Returns a hash code from a string - * @param {String} str The string to hash. - * @return {Number} A 32bit integer (can be negative) + * @param str The string to hash. + * @return A 32bit integer (can be negative) * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ */ -function hashCode(str) { +function hashCode(str: string): number { let hash = 0; for (let i = 0, len = str.length; i < len; i++) { const chr = str.charCodeAt(i); diff --git a/src/libs/isInputAutoFilled.js b/src/libs/isInputAutoFilled.ts similarity index 66% rename from src/libs/isInputAutoFilled.js rename to src/libs/isInputAutoFilled.ts index 8daa72484647..0abe634001e4 100644 --- a/src/libs/isInputAutoFilled.js +++ b/src/libs/isInputAutoFilled.ts @@ -2,11 +2,9 @@ import isSelectorSupported from './isSelectorSupported'; /** * Check the input is auto filled or not - * @param {Object} input - * @return {Boolean} */ -export default function isInputAutoFilled(input) { - if (!input || !input.matches) return false; +export default function isInputAutoFilled(input: Element): boolean { + if (!input?.matches) return false; if (isSelectorSupported(':autofill')) { return input.matches(':-webkit-autofill') || input.matches(':autofill'); } diff --git a/src/libs/isReportMessageAttachment.ts b/src/libs/isReportMessageAttachment.ts index 3f9e9d2de201..c257e1db4191 100644 --- a/src/libs/isReportMessageAttachment.ts +++ b/src/libs/isReportMessageAttachment.ts @@ -13,14 +13,14 @@ type IsReportMessageAttachmentParams = { * @param reportActionMessage report action's message as text, html and translationKey */ export default function isReportMessageAttachment({text, html, translationKey}: IsReportMessageAttachmentParams): boolean { - if (translationKey) { - return translationKey === CONST.TRANSLATION_KEYS.ATTACHMENT; - } - if (!text || !html) { return false; } + if (translationKey && text === CONST.ATTACHMENT_MESSAGE_TEXT) { + return translationKey === CONST.TRANSLATION_KEYS.ATTACHMENT; + } + const regex = new RegExp(` ${CONST.ATTACHMENT_SOURCE_ATTRIBUTE}="(.*)"`, 'i'); return text === CONST.ATTACHMENT_MESSAGE_TEXT && (!!html.match(regex) || html === CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML); } diff --git a/src/libs/tryResolveUrlFromApiRoot.js b/src/libs/tryResolveUrlFromApiRoot.ts similarity index 85% rename from src/libs/tryResolveUrlFromApiRoot.js rename to src/libs/tryResolveUrlFromApiRoot.ts index cc46f034e45b..f9aef09a00a7 100644 --- a/src/libs/tryResolveUrlFromApiRoot.js +++ b/src/libs/tryResolveUrlFromApiRoot.ts @@ -15,11 +15,10 @@ const ORIGIN_PATTERN = new RegExp(`^(${ORIGINS_TO_REPLACE.join('|')})`); * - Similarly for prod or staging URLs we replace the `https://www.expensify` * or `https://staging.expensify` part, with `https://{API_ROOT}` * - Unmatched URLs (non expensify) are returned with no modifications - * - * @param {String} url - * @returns {String} */ -export default function tryResolveUrlFromApiRoot(url) { +function tryResolveUrlFromApiRoot(url: string): string; +function tryResolveUrlFromApiRoot(url: number): number; +function tryResolveUrlFromApiRoot(url: string | number): string | number { // in native, when we import an image asset, it will have a number representation which can be used in `source` of Image // in this case we can skip the url resolving if (typeof url === 'number') { @@ -28,3 +27,5 @@ export default function tryResolveUrlFromApiRoot(url) { const apiRoot = ApiUtils.getApiRoot({shouldUseSecure: false}); return url.replace(ORIGIN_PATTERN, apiRoot); } + +export default tryResolveUrlFromApiRoot; diff --git a/src/libs/willBlurTextInputOnTapOutside/index.js b/src/libs/willBlurTextInputOnTapOutside/index.js deleted file mode 100644 index 3c72b2d38a29..000000000000 --- a/src/libs/willBlurTextInputOnTapOutside/index.js +++ /dev/null @@ -1 +0,0 @@ -export default () => true; diff --git a/src/libs/willBlurTextInputOnTapOutside/index.native.js b/src/libs/willBlurTextInputOnTapOutside/index.native.js deleted file mode 100644 index eae5767cffbc..000000000000 --- a/src/libs/willBlurTextInputOnTapOutside/index.native.js +++ /dev/null @@ -1 +0,0 @@ -export default () => false; diff --git a/src/libs/willBlurTextInputOnTapOutside/index.native.ts b/src/libs/willBlurTextInputOnTapOutside/index.native.ts new file mode 100644 index 000000000000..1cf1bbafe7e6 --- /dev/null +++ b/src/libs/willBlurTextInputOnTapOutside/index.native.ts @@ -0,0 +1,5 @@ +import WillBlurTextInputOnTapOutside from './types'; + +const willBlurTextInputOnTapOutside: WillBlurTextInputOnTapOutside = () => false; + +export default willBlurTextInputOnTapOutside; diff --git a/src/libs/willBlurTextInputOnTapOutside/index.ts b/src/libs/willBlurTextInputOnTapOutside/index.ts new file mode 100644 index 000000000000..7c88957821b3 --- /dev/null +++ b/src/libs/willBlurTextInputOnTapOutside/index.ts @@ -0,0 +1,5 @@ +import WillBlurTextInputOnTapOutside from './types'; + +const willBlurTextInputOnTapOutside: WillBlurTextInputOnTapOutside = () => true; + +export default willBlurTextInputOnTapOutside; diff --git a/src/libs/willBlurTextInputOnTapOutside/types.ts b/src/libs/willBlurTextInputOnTapOutside/types.ts new file mode 100644 index 000000000000..1ef88eb98f8c --- /dev/null +++ b/src/libs/willBlurTextInputOnTapOutside/types.ts @@ -0,0 +1,3 @@ +type WillBlurTextInputOnTapOutside = () => boolean; + +export default WillBlurTextInputOnTapOutside; diff --git a/src/pages/DemoSetupPage.js b/src/pages/DemoSetupPage.js index 0f7578760c16..5d4b99a0daf9 100644 --- a/src/pages/DemoSetupPage.js +++ b/src/pages/DemoSetupPage.js @@ -2,9 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import {useFocusEffect} from '@react-navigation/native'; import FullScreenLoadingIndicator from '../components/FullscreenLoadingIndicator'; -import CONST from '../CONST'; -import * as DemoActions from '../libs/actions/DemoActions'; import Navigation from '../libs/Navigation/Navigation'; +import ROUTES from '../ROUTES'; const propTypes = { /** Navigation route context info provided by react navigation */ @@ -15,22 +14,14 @@ const propTypes = { }; /* - * This is a "utility page", that does this: - * - Looks at the current route - * - Determines if there's a demo command we need to call - * - If not, routes back to home + * This is a "utility page", that used to call specific actions depending on the + * route that led the user here. Now, it's just used to route the user home so we + * don't show them a "Hmm... It's not here" message (which looks broken). */ -function DemoSetupPage(props) { +function DemoSetupPage() { useFocusEffect(() => { Navigation.isNavigationReady().then(() => { - // Depending on the route that the user hit to get here, run a specific demo flow - if (props.route.name === CONST.DEMO_PAGES.SAASTR) { - DemoActions.runSaastrDemo(); - } else if (props.route.name === CONST.DEMO_PAGES.SBE) { - DemoActions.runSbeDemo(); - } else { - Navigation.goBack(); - } + Navigation.goBack(ROUTES.HOME); }); }); diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 83b0019315e4..266515e29c2c 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -18,6 +18,7 @@ import EditRequestAmountPage from './EditRequestAmountPage'; import reportPropTypes from './reportPropTypes'; import * as IOU from '../libs/actions/IOU'; import * as CurrencyUtils from '../libs/CurrencyUtils'; +import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; const propTypes = { /** Route from navigation */ @@ -168,7 +169,7 @@ function EditRequestPage({report, route, parentReport, policy, session}) { ); } - return null; + return ; } EditRequestPage.displayName = 'EditRequestPage'; diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index b5ef85e14cbb..22cac40cf29c 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -141,7 +141,7 @@ function ProfilePage(props) { const navigateBackTo = lodashGet(props.route, 'params.backTo', ''); return ( - + Navigation.goBack(navigateBackTo)} diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index d76d10c9e52c..22133415cea8 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -224,7 +224,7 @@ function CompanyStep({reimbursementAccount, reimbursementAccountDraft, getDefaul ({value, label}))} + items={_.map(_.keys(CONST.INCORPORATION_TYPES), (key) => ({value: key, label: translate(`companyStep.incorporationTypes.${key}`)}))} placeholder={{value: '', label: '-'}} defaultValue={getDefaultStateForField('incorporationType')} shouldSaveDraft diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 6505b604b614..dd42ed80c3d4 100755 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import React, {Component} from 'react'; +import React, {useCallback, useEffect, useState, useMemo} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; @@ -9,17 +9,15 @@ import * as ReportUtils from '../libs/ReportUtils'; import ONYXKEYS from '../ONYXKEYS'; import styles from '../styles/styles'; import Navigation from '../libs/Navigation/Navigation'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../components/withWindowDimensions'; import * as Report from '../libs/actions/Report'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import ScreenWrapper from '../components/ScreenWrapper'; import Timing from '../libs/actions/Timing'; import CONST from '../CONST'; -import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; -import compose from '../libs/compose'; import personalDetailsPropType from './personalDetailsPropType'; import reportPropTypes from './reportPropTypes'; import Performance from '../libs/Performance'; +import useLocalize from '../hooks/useLocalize'; const propTypes = { /* Onyx Props */ @@ -32,11 +30,6 @@ const propTypes = { /** All reports shared with the user */ reports: PropTypes.objectOf(reportPropTypes), - - /** Window Dimensions Props */ - ...windowDimensionsPropTypes, - - ...withLocalizePropTypes, }; const defaultProps = { @@ -45,171 +38,157 @@ const defaultProps = { reports: {}, }; -class SearchPage extends Component { - constructor(props) { - super(props); +function SearchPage({betas, personalDetails, reports}) { + // Data for initialization (runs only on the first render) + const { + recentReports: initialRecentReports, + personalDetails: initialPersonalDetails, + userToInvite: initialUserToInvite, + // Ignoring the rule because in this case we need the data only initially + // eslint-disable-next-line react-hooks/exhaustive-deps + } = useMemo(() => OptionsListUtils.getSearchOptions(reports, personalDetails, '', betas), []); + + const [searchValue, setSearchValue] = useState(''); + const [searchOptions, setSearchOptions] = useState({ + recentReports: initialRecentReports, + personalDetails: initialPersonalDetails, + userToInvite: initialUserToInvite, + }); + + const {translate} = useLocalize(); + + const updateOptions = useCallback(() => { + const { + recentReports: localRecentReports, + personalDetails: localPersonalDetails, + userToInvite: localUserToInvite, + } = OptionsListUtils.getSearchOptions(reports, personalDetails, searchValue.trim(), betas); + + setSearchOptions({ + recentReports: localRecentReports, + personalDetails: localPersonalDetails, + userToInvite: localUserToInvite, + }); + }, [reports, personalDetails, searchValue, betas]); + + const debouncedUpdateOptions = useMemo(() => _.debounce(updateOptions, 75), [updateOptions]); + useEffect(() => { Timing.start(CONST.TIMING.SEARCH_RENDER); Performance.markStart(CONST.TIMING.SEARCH_RENDER); + }, []); - this.searchRendered = this.searchRendered.bind(this); - this.selectReport = this.selectReport.bind(this); - this.onChangeText = this.onChangeText.bind(this); - this.debouncedUpdateOptions = _.debounce(this.updateOptions.bind(this), 75); - - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getSearchOptions(props.reports, props.personalDetails, '', props.betas); - - this.state = { - searchValue: '', - recentReports, - personalDetails, - userToInvite, - }; - } - - componentDidUpdate(prevProps) { - if (_.isEqual(prevProps.reports, this.props.reports) && _.isEqual(prevProps.personalDetails, this.props.personalDetails)) { - return; - } - this.updateOptions(); - } - - onChangeText(searchValue = '') { - this.setState({searchValue}, this.debouncedUpdateOptions); - } + useEffect(() => { + debouncedUpdateOptions(); + }, [searchValue, debouncedUpdateOptions]); /** * Returns the sections needed for the OptionsSelector * * @returns {Array} */ - getSections() { + const getSections = () => { const sections = []; let indexOffset = 0; - if (this.state.recentReports.length > 0) { + if (searchOptions.recentReports.length > 0) { sections.push({ - data: this.state.recentReports, + data: searchOptions.recentReports, shouldShow: true, indexOffset, }); - indexOffset += this.state.recentReports.length; + indexOffset += searchOptions.recentReports.length; } - if (this.state.personalDetails.length > 0) { + if (searchOptions.personalDetails.length > 0) { sections.push({ - data: this.state.personalDetails, + data: searchOptions.personalDetails, shouldShow: true, indexOffset, }); - indexOffset += this.state.recentReports.length; + indexOffset += searchOptions.recentReports.length; } - if (this.state.userToInvite) { + if (searchOptions.userToInvite) { sections.push({ - data: [this.state.userToInvite], + data: [searchOptions.userToInvite], shouldShow: true, indexOffset, }); } return sections; - } + }; - searchRendered() { + const searchRendered = () => { Timing.end(CONST.TIMING.SEARCH_RENDER); Performance.markEnd(CONST.TIMING.SEARCH_RENDER); - } - - updateOptions() { - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getSearchOptions( - this.props.reports, - this.props.personalDetails, - this.state.searchValue.trim(), - this.props.betas, - ); - this.setState({ - userToInvite, - recentReports, - personalDetails, - }); - } + }; + + const onChangeText = (value = '') => { + setSearchValue(value); + }; /** * Reset the search value and redirect to the selected report * * @param {Object} option */ - selectReport(option) { + const selectReport = (option) => { if (!option) { return; } - if (option.reportID) { - this.setState( - { - searchValue: '', - }, - () => { - Navigation.dismissModal(option.reportID); - }, - ); + setSearchValue(''); + Navigation.dismissModal(option.reportID); } else { Report.navigateToAndOpenReport([option.login]); } - } - - render() { - const sections = this.getSections(); - const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(this.props.personalDetails); - const headerMessage = OptionsListUtils.getHeaderMessage( - this.state.recentReports.length + this.state.personalDetails.length !== 0, - Boolean(this.state.userToInvite), - this.state.searchValue, - ); - - return ( - - {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( - <> - - - - - - )} - - ); - } + }; + + const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); + const headerMessage = OptionsListUtils.getHeaderMessage( + searchOptions.recentReports.length + searchOptions.personalDetails.length !== 0, + Boolean(searchOptions.userToInvite), + searchValue, + ); + return ( + + {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( + <> + + + + + + )} + + ); } SearchPage.propTypes = propTypes; SearchPage.defaultProps = defaultProps; - -export default compose( - withLocalize, - withWindowDimensions, - withOnyx({ - reports: { - key: ONYXKEYS.COLLECTION.REPORT, - }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - betas: { - key: ONYXKEYS.BETAS, - }, - }), -)(SearchPage); +SearchPage.displayName = 'SearchPage'; +export default withOnyx({ + reports: { + key: ONYXKEYS.COLLECTION.REPORT, + }, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + betas: { + key: ONYXKEYS.BETAS, + }, +})(SearchPage); diff --git a/src/pages/TeachersUnite/ImTeacherPage.js b/src/pages/TeachersUnite/ImTeacherPage.js index f077c7724978..dbeba700d208 100644 --- a/src/pages/TeachersUnite/ImTeacherPage.js +++ b/src/pages/TeachersUnite/ImTeacherPage.js @@ -22,7 +22,7 @@ function ImTeacherPage() { Navigation.goBack(ROUTES.SAVE_THE_WORLD)} + onBackButtonPress={() => Navigation.goBack(ROUTES.TEACHERS_UNITE)} /> Navigation.goBack(ROUTES.SAVE_THE_WORLD)} + onBackButtonPress={() => Navigation.goBack(ROUTES.TEACHERS_UNITE)} />
Navigation.goBack(ROUTES.SAVE_THE_WORLD)} + onBackButtonPress={() => Navigation.goBack(ROUTES.TEACHERS_UNITE)} /> { + if (_.isEmpty(props.reportActions) || props.reportActionID === '0') return {}; + return props.reportActions[props.reportActionID] || {}; + }, [props.reportActions, props.reportActionID]); + const shouldShowFilter = (contextAction) => - contextAction.shouldShow( - props.type, - props.reportAction, - props.isArchivedRoom, - props.betas, - props.anchor, - props.isChronosReport, - props.reportID, - props.isPinnedChat, - props.isUnreadChat, - ); + contextAction.shouldShow(props.type, reportAction, props.isArchivedRoom, props.betas, props.anchor, props.isChronosReport, props.reportID, props.isPinnedChat, props.isUnreadChat); /** * Checks if user is anonymous. If true and the action doesn't accept for anonymous user, hides the context menu and @@ -85,7 +84,7 @@ function BaseReportActionContextMenu(props) { {_.map(_.filter(ContextMenuActions, shouldShowFilter), (contextAction) => { const closePopup = !props.isMini; const payload = { - reportAction: props.reportAction, + reportAction, reportID: props.reportID, draftMessage: props.draftMessage, selection: props.selection, @@ -106,7 +105,7 @@ function BaseReportActionContextMenu(props) { return ( `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`, + canEvict: false, + }, + }), +)( + memo(BaseReportActionContextMenu, (prevProps, nextProps) => { + const prevReportAction = lodashGet(prevProps.reportActions, prevProps.reportActionID, ''); + const nextReportAction = lodashGet(nextProps.reportActions, nextProps.reportActionID, ''); + + // We only want to re-render when the report action that is attached to is changed + if (prevReportAction !== nextReportAction) { + return false; + } + return _.isEqual(_.omit(prevProps, 'reportActions'), _.omit(nextProps, 'reportActions')); + }), +); diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js index 81858564b416..3633fb99fc32 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js @@ -21,7 +21,8 @@ class PopoverReportActionContextMenu extends React.Component { this.state = { reportID: '0', - reportAction: {}, + reportActionID: '0', + originalReportID: '0', selection: '', reportActionDraftMessage: '', isPopoverVisible: false, @@ -112,7 +113,7 @@ class PopoverReportActionContextMenu extends React.Component { * @return {Boolean} */ isActiveReportAction(actionID) { - return Boolean(actionID) && this.state.reportAction.reportActionID === actionID; + return Boolean(actionID) && this.state.reportActionID === actionID; } /** @@ -123,7 +124,8 @@ class PopoverReportActionContextMenu extends React.Component { * @param {String} [selection] - Copied content. * @param {Element} contextMenuAnchor - popoverAnchor * @param {String} reportID - Active Report Id - * @param {Object} reportAction - ReportAction for ContextMenu + * @param {Object} reportActionID - ReportAction for ContextMenu + * @param {String} originalReportID - The currrent Report Id of the reportAction * @param {String} draftMessage - ReportAction Draftmessage * @param {Function} [onShow] - Run a callback when Menu is shown * @param {Function} [onHide] - Run a callback when Menu is hidden @@ -138,7 +140,8 @@ class PopoverReportActionContextMenu extends React.Component { selection, contextMenuAnchor, reportID, - reportAction, + reportActionID, + originalReportID, draftMessage, onShow = () => {}, onHide = () => {}, @@ -170,7 +173,8 @@ class PopoverReportActionContextMenu extends React.Component { }, type, reportID, - reportAction, + reportActionID, + originalReportID, selection, isPopoverVisible: true, reportActionDraftMessage: draftMessage, @@ -216,7 +220,7 @@ class PopoverReportActionContextMenu extends React.Component { * After Popover hides, call the registered onPopoverHide & onPopoverHideActionCallback callback and reset it */ runAndResetOnPopoverHide() { - this.setState({reportID: '0', reportAction: {}}, () => { + this.setState({reportID: '0', reportActionID: '0', originalReportID: '0'}, () => { this.onPopoverHide = this.runAndResetCallback(this.onPopoverHide); this.onPopoverHideActionCallback = this.runAndResetCallback(this.onPopoverHideActionCallback); }); @@ -310,7 +314,7 @@ class PopoverReportActionContextMenu extends React.Component { isVisible type={this.state.type} reportID={this.state.reportID} - reportAction={this.state.reportAction} + reportActionID={this.state.reportActionID} draftMessage={this.state.reportActionDraftMessage} selection={this.state.selection} isArchivedRoom={this.state.isArchivedRoom} @@ -319,6 +323,7 @@ class PopoverReportActionContextMenu extends React.Component { isUnreadChat={this.state.isUnreadChat} anchor={this.contextMenuTargetNode} contentRef={this.contentRef} + originalReportID={this.state.originalReportID} /> {}) { * @param {String} [selection] - Copied content. * @param {Element} contextMenuAnchor - popoverAnchor * @param {String} reportID - Active Report Id - * @param {Object} reportAction - ReportAction for ContextMenu + * @param {String} reportActionID - ReportActionID for ContextMenu + * @param {String} originalReportID - The currrent Report Id of the reportAction * @param {String} draftMessage - ReportAction Draftmessage * @param {Function} [onShow=() => {}] - Run a callback when Menu is shown * @param {Function} [onHide=() => {}] - Run a callback when Menu is hidden @@ -54,7 +55,8 @@ function showContextMenu( selection, contextMenuAnchor, reportID = '0', - reportAction = {}, + reportActionID = '0', + originalReportID = '0', draftMessage = '', onShow = () => {}, onHide = () => {}, @@ -72,13 +74,15 @@ function showContextMenu( hideContextMenu(); contextMenuRef.current.runAndResetOnPopoverHide(); } + contextMenuRef.current.showContextMenu( type, event, selection, contextMenuAnchor, reportID, - reportAction, + reportActionID, + originalReportID, draftMessage, onShow, onHide, diff --git a/src/pages/home/report/ContextMenu/genericReportActionContextMenuPropTypes.js b/src/pages/home/report/ContextMenu/genericReportActionContextMenuPropTypes.js index f62873031c54..3d8667e44e62 100644 --- a/src/pages/home/report/ContextMenu/genericReportActionContextMenuPropTypes.js +++ b/src/pages/home/report/ContextMenu/genericReportActionContextMenuPropTypes.js @@ -1,12 +1,14 @@ import PropTypes from 'prop-types'; -import reportActionPropTypes from '../reportActionPropTypes'; const propTypes = { /** The ID of the report this report action is attached to. */ reportID: PropTypes.string.isRequired, - /** The report action this context menu is attached to. */ - reportAction: PropTypes.shape(reportActionPropTypes).isRequired, + /** The ID of the report action this context menu is attached to. */ + reportActionID: PropTypes.string.isRequired, + + /** The ID of the original report from which the given reportAction is first created. */ + originalReportID: PropTypes.string.isRequired, /** If true, this component will be a small, row-oriented menu that displays icons but not text. If false, this component will be a larger, column-oriented menu that displays icons alongside text in each row. */ diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js index 5864b9b05023..6dd3355f4a53 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js @@ -76,6 +76,9 @@ const propTypes = { /** Called when the add action button is pressed */ onAddActionPressed: PropTypes.func.isRequired, + /** Called when the menu item is selected */ + onItemSelected: PropTypes.func.isRequired, + /** A ref for the add action button */ actionButtonRef: PropTypes.shape({ // eslint-disable-next-line react/forbid-prop-types @@ -111,6 +114,7 @@ function AttachmentPickerWithMenuItems({ onCanceledAttachmentPicker, onMenuClosed, onAddActionPressed, + onItemSelected, actionButtonRef, }) { const {translate} = useLocalize(); @@ -257,6 +261,7 @@ function AttachmentPickerWithMenuItems({ onClose={onPopoverMenuClose} onItemSelected={(item, index) => { setMenuVisibility(false); + onItemSelected(); // In order for the file picker to open dynamically, the click // function must be called from within a event handler that was initiated diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js index 36b0af156ae5..3b5b181d2fcb 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js @@ -321,11 +321,11 @@ function ComposerWithSuggestions({ suggestionsRef.current.updateShouldShowSuggestionMenuToFalse(false); }, [suggestionsRef]); - const setShouldBlockSuggestionCalc = useCallback(() => { + const setShouldBlockSuggestionCalcToFalse = useCallback(() => { if (!suggestionsRef.current) { return false; } - return suggestionsRef.current.setShouldBlockSuggestionCalc(true); + return suggestionsRef.current.setShouldBlockSuggestionCalc(false); }, [suggestionsRef]); /** @@ -353,9 +353,10 @@ function ComposerWithSuggestions({ * @returns {Boolean} */ const checkComposerVisibility = useCallback(() => { - const isComposerCoveredUp = EmojiPickerActions.isEmojiPickerVisible() || isMenuVisible || modal.isVisible; + // Checking whether the screen is focused or not, helps avoid `modal.isVisible` false when popups are closed, even if the modal is opened. + const isComposerCoveredUp = !isFocused || EmojiPickerActions.isEmojiPickerVisible() || isMenuVisible || modal.isVisible || modal.willAlertModalBecomeVisible; return !isComposerCoveredUp; - }, [isMenuVisible, modal.isVisible]); + }, [isMenuVisible, modal, isFocused]); const focusComposerOnKeyPress = useCallback( (e) => { @@ -471,7 +472,7 @@ function ComposerWithSuggestions({ maxLines={maxComposerLines} onFocus={onFocus} onBlur={onBlur} - onClick={setShouldBlockSuggestionCalc} + onClick={setShouldBlockSuggestionCalcToFalse} onPasteFile={displayFileInModal} shouldClear={textInputShouldClear} onClear={() => setTextInputShouldClear(false)} diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose/ReportActionCompose.js index 3ad92fa5c769..89ed9ded787e 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.js @@ -75,7 +75,6 @@ const propTypes = { }; const defaultProps = { - modal: {}, report: {}, blockedFromConcierge: {}, personalDetails: {}, @@ -205,6 +204,10 @@ function ReportActionCompose({ composerRef.current.blur(); }, []); + const onItemSelected = useCallback(() => { + isKeyboardVisibleWhenShowingModalRef.current = false; + }, []); + const updateShouldShowSuggestionMenuToFalse = useCallback(() => { if (!suggestionsRef.current) { return; @@ -271,6 +274,7 @@ function ReportActionCompose({ suggestionsRef.current.setShouldBlockSuggestionCalc(true); } isNextModalWillOpenRef.current = true; + isKeyboardVisibleWhenShowingModalRef.current = true; }, []); const onBlur = useCallback((e) => { @@ -358,6 +362,7 @@ function ReportActionCompose({ onCanceledAttachmentPicker={restoreKeyboardState} onMenuClosed={restoreKeyboardState} onAddActionPressed={onAddActionPressed} + onItemSelected={onItemSelected} actionButtonRef={actionButtonRef} /> { + setIsHidden(isHiddenValue); + const isAttachment = ReportUtils.isReportMessageAttachment(_.last(props.action.message)); + if (!isAttachment) { + return; + } + updateHiddenAttachments(props.action.reportActionID, isHiddenValue); + }, + [props.action.reportActionID, props.action.message, updateHiddenAttachments], + ); + useEffect( () => () => { // ReportActionContextMenu, EmojiPicker and PopoverReactionList are global components, @@ -231,7 +245,8 @@ function ReportActionItem(props) { selection, popoverAnchorRef, props.report.reportID, - props.action, + props.action.reportActionID, + originalReportID, props.draftMessage, () => {}, toggleContextMenuFromActiveReportAction, @@ -239,7 +254,7 @@ function ReportActionItem(props) { ReportUtils.chatIncludesChronos(originalReport), ); }, - [props.draftMessage, props.action, props.report.reportID, toggleContextMenuFromActiveReportAction, originalReport], + [props.draftMessage, props.action, props.report.reportID, toggleContextMenuFromActiveReportAction, originalReport, originalReportID], ); const toggleReaction = useCallback( @@ -369,7 +384,7 @@ function ReportActionItem(props) {